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

Универсальный порт для Cortex-Mx (GCC) залит в репозиторий.

Всем привет.

Добрался до 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.

Замечания и предложения приветствуютсяsm.gif

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


Ссылка на сообщение
Поделиться на другие сайты
Цитата(AHTOXA @ Mar 31 2015, 22:03) <{POST_SNAPBACK}>
Замечания и предложения приветствуютсяsm.gif

Ну раз так, то настало время спросить.
startup.c: Почему бы не разогнать ядро, выполнив init_HW() до инициализации .bss и .data?
Зачем нужен __attribute__((__interrupt__)) для void Reset_Handler(void)? В стандартных шаблонах от производителей этого нет.
sysinit.cpp: Не кошернее ли enable IOPx peripheral делать не в общем для всех случаев файле, а на уровне конкретного проекта?

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


Ссылка на сообщение
Поделиться на другие сайты
Цитата(IgorKossak @ Apr 3 2015, 13:45) <{POST_SNAPBACK}>
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. Привычка к нормализацииsm.gif

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


Ссылка на сообщение
Поделиться на другие сайты
Обнаружил баг. Оказывается, Cortex-M0 не позволяет побайтовый доступ к регистрам System Control Block (SCB).
Поэтому некорректно устанавливались приоритеты обработчиков прерываний PendSV и SysTick.
Исправил в rev. 586.

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


Ссылка на сообщение
Поделиться на другие сайты
В более ранних версиях приоритеты обработчиков прерываний PendSV и SysTick устанавливались как
Код
    SCB->SHPR3 = 0
            | (3 << 22)     // PendSV priority = 3, lowest
            | (2 << 30)     // SysTick priority = 2, little higher
           ;

Сейчас они устанавливаются одинаковыми, хоть и наинизшими. Есть какая-то причина?

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


Ссылка на сообщение
Поделиться на другие сайты
Нет, какой-то особой причины нет. Просто я сделал так, как было в порте для M3/M4. Там всю дорогу были одинаковые (наинизшие) приоритеты для PendSV и SysTick. Я подумал, что у M0 приоритетов и так мало, и жалко тратить аж два уровня из них на ось.
К тому же, инициализация SysTick сделана опциональной, так что пользователь всегда может написать свой вариант функции __init_system_timer(), в которой задаст нужный ему приоритет.
А зачем может быть нужно, чтобы SysTick мог прерывать PendSV?

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


Ссылка на сообщение
Поделиться на другие сайты
Я имел в виду другое. Возможно в более ранней версии для порта Cortex M0 была причина сделать так, чтобы PendSV могла быть вытеснена любым другим прерыванием, в том числе и SysTick.
Об этом неплохо бы у Сергея Борща спросить wink.gif
ПС: В порте для Cortex M3 приоритеты одинаковые.
Изменено пользователем IgorKossak

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


Ссылка на сообщение
Поделиться на другие сайты
Да простая там идея - чтобы перепланировка выполнялась после всех прерываний, которые могут эту перепланировку потребовать. Чтобы не перепланировать дважды. Само прерывание перепланировки выполняется с запрещенными прерываниями и прервать его никто не может.

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


Ссылка на сообщение
Поделиться на другие сайты
Ага, то есть, если за время обработки какого-нибудь более приоритетного прерывания взведутся флаги SysTick и PendSV, то, при одинаковых приоритетах, сначала сработает PendSV, и уже потом SysTick, который в свою очередь может взвести флаг PendSV.
А если мы поднимем приоритет SysTick-а, то всё сработает как надо - сначала SysTick, и уже потом PendSV. Так?

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


Ссылка на сообщение
Поделиться на другие сайты
Цитата(AHTOXA @ Apr 16 2015, 20:58) <{POST_SNAPBACK}>
А если мы поднимем приоритет SysTick-а, то всё сработает как надо - сначала SysTick, и уже потом PendSV. Так?
Именно.

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


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

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


Ссылка на сообщение
Поделиться на другие сайты
Цитата(AHTOXA @ Apr 17 2015, 08:37) <{POST_SNAPBACK}>
Тогда надо приподнять. Сделаю на днях.

Величины приоритетов сейчас задаются жёстко в файле OS_Target_cpp.cpp на уровне порта.
Величина "приподнимания" в случае с Cortex M3/4 будет зависеть от параметра функции NVIC_SetPriorityGrouping(n), в функции void init_HW(void) в файле sysinit.cpp на уровне приложения. На мой взгляд такое распределение не очень удобно. Может лучше эти магические числа вынести куда-нибудь в scmRTOS_TARGET_CFG.h?

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


Ссылка на сообщение
Поделиться на другие сайты
Нас не волнует группировка приоритетов, нам же не надо, чтобы 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, то оставляем старое поведение.

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


Ссылка на сообщение
Поделиться на другие сайты
То есть в порт добавляется еще куча объявлений уровня проекта. Зачем вообще пихать это все в ОСь? Достаточно попросить пользователя настроить эти два прерывания и системный таймер где, когда и как ему будет удобно.

Я вообще делаю все настройки периферии в стартапе и мне совершенно не нужны эти определения. Более того, меня напрягает необходимость сейчас передавать в потроха ОСи значение тактовой частоты.

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


Ссылка на сообщение
Поделиться на другие сайты
Какая куча? Добавляется всего одно объявление, причём как раз на уровне проекта. А в порте - fallback для старых проектов, в которых нет этого объявления. Как здесь можно сделать иначе?
Что касаемо вообще настройки таймера в порте, а не в проекте - так уж исторически сложилось. В ядре есть специальный таймер для оси, поэтому удобно иметь настройку этого таймера на уровне порта. Вот например, сейчас - выяснилось, что полезно иметь приоритет системного таймера чуть повыше, чем приоритет прерывания планировщика. Я исправлю порт, и все проекты, использующие этот порт, автоматически получат это исправление. Разве это не хорошо?
Возможность выбрать другой таймер - есть. Возможность заменить функцию инициализации таймера на свою - тоже есть.
Естественно, такого рода вариативность требует некоторых телодвижений, типа задания значение тактовой частоты. Я думаю, что это небольшая плата за гибкость.

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


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

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
Авторизация