Jump to content

    

nRF52 BLE SDK (Cortex M3) SVC

Здравствуйте!

 

кто нибудь пытался вести разработку на scmRTOS для nRF52 BLE SDK ?

 

Как сочетать API взаимодействия BLE стэка (прошивки) работающее по SVC вызовам ?

 

спасибо!

 

 

Share this post


Link to post
Share on other sites

В nRF SDK есть же примеры с FreeRTOS. Да и nRF52 это Cortex-M4F

Share this post


Link to post
Share on other sites
Вот тут недавно что-то проскакивало про NRF: ссылка.

Коллега sevstels, к сожалению, забил на требование нордика "никогда не отключайте прерывания при работе softdevice'а".

А может, он и не использовал софтдевайс - в примере нет, в сообщениях на форуме "все дураки, я свой велосипед строю"...

 

 

В nRF SDK есть же примеры с FreeRTOS. Да и nRF52 это Cortex-M4F

Есть, да.

Надо взять порт scmRTOS от STM'ки, переписать критическую секцию, таймер (systick в nrf52 вернули обратно, но он батарейку жрёт), и отладить.

Ну и в процессе раскурить, что они с приоритетами прерываний сделали (нормального описания я не нашёл, к сожалению, только в духе "trust me, i know what i'm doing").

 

Наличие готового примера и грамотного человека, который это делал, процесс должно сильно ускорить. Ну да ладно, будет повод самому описать...

Share this post


Link to post
Share on other sites

Продолжаем.

 

Коллеги, у меня вопрос.

Техподдержка Nordic запрещает отключать прерывания, используемые softdevice'ом (это стек блютус, исполняемый на том же процессоре, что и пользовательский код; поставляется как единый hex с документированными точками входа).

 

Для организации критических секций у них предусмотрен следующий костыль:

https://github.com/NordicPlayground/nrf52-b...nrf_nvic.h#L437

sd_nvic_critical_region_enter(), sd_nvic_critical_region_exit()

Т.е:

- запретить все прерывания

- сохранить во временную переменную регистры разрешённых прерываний

- обнулить эти регистры (точнее, записать маску "только прерывания softdevice'а)

- разрешить прерывания

 

При этом:

- допустимые ядром приоритеты прерываний - 0..7

- софтдевайс использует приоритеты 0 и 4 (во всяком случае, так в последнем SDK 15.0, в документации это не описано)

 

Ваше мнение, как лучше:

- обернуть эти функции в OS::TCritSect

- оставить обычную критическую секцию - они всё равно делают disable_irq()/enable_irq(), несмотря на заявление техподдержки "прерывания отключать нельзя, ни на 1 секунду, ни на 1 микросекунду"

- сделать прерывания ОС и пользовательского кода с приоритетом 5..7 и разобраться с запретом через изменение регистра BASEPRI

Share this post


Link to post
Share on other sites
sd_nvic_critical_region_enter(), sd_nvic_critical_region_exit()

Т.е:

- запретить все прерывания

- сохранить во временную переменную регистры заррешённых прерываний

- обнулить эти регистры (точнее, записать маску "только прерывания softdevice'а)

- разрешить прерывания

Ваше мнение, как лучше:

Я бы последовал их рекомендации, но с оптимизацией её: сохранять/обнулять не все биты разрешения прерываний, а только важные для данной конкретной критической секции.

Такая оптимизация позволит сэкономить и такты и байты.

Share this post


Link to post
Share on other sites

Не вижу особой пользы.

Как оно экономит? Уменьшается latency, но (забыл сказать) мне оно некритично. Общая скорость не растёт, размер не уменьшается.

 

Геморрой только добавляется, т.к. эту оптимизацию руками надо делать, и постоянно следить, чтобы из N-цати кртитических секций выбрать нужную.

Share this post


Link to post
Share on other sites
Не вижу особой пользы.

Как оно экономит? Уменьшается latency, но (забыл сказать) мне оно некритично. Общая скорость не растёт, размер не уменьшается.

В смысле "как"? Работа с одной переменной ведь проще/быстрее чем с несколькими. Не находите?

Не знаю сколько прерываний в вашем МК, но в моём сейчас их биты масок растянулись аж на 4-е 32-битных регистра. Это значит что в критической секции которая без разбора запрещает всё, надо будет все 4 регистра прочитать, сохранить и записать в них маскирующие значения. Что довольно-таки долго и в каждом таком месте требует 4 слова по 32 бита.

В то время как данная критическая секция может нужна для защиты всего от одного прерывания (только один регистр можно сохранить, одно прерывание запретить).

 

И если Вы говорите что латентность Вас не беспокоит, то к чему тогда вообще был вопрос? Вы же спрашивали насчёт наиболее оптимального способа? Или нет?

 

Геморрой только добавляется, т.к. эту оптимизацию руками надо делать, и постоянно следить, чтобы из N-цати кртитических секций выбрать нужную.

Геморрой это только если без головы делать. С умом если, то достаточно написать макрос в котором на входе задаётся маска интересующих прерываний, а внутри он по этой маске всю работу и сделает.

И вообще-то в серьёзных системах там так и есть - для каждого защищаемого объекта - своя критическая секция. Например в винде. А то что Вы называете критической секцией, это просто запрет прерывания и в действительности не является критической секцией.

 

PS: Кстати - маскирование прерываний через NVIC не запрещает все прерывания. Есть ещё Systick и PendSV и другие fault-ы (если они у Вас используются).

Share this post


Link to post
Share on other sites
В смысле "как"? Работа с одной переменной ведь проще/быстрее чем с несколькими. Не находите?

Не знаю сколько прерываний в вашем МК,

Он указан. Точнее, указано семейство, но внутри семейства они достаточно одинаковые.

 

Что довольно-таки долго и в каждом таком месте требует 4 слова по 32 бита.

В решении "запретить всё", кстати, хранилище только одно.

 

И если Вы говорите что латентность Вас не беспокоит, то к чему тогда вообще был вопрос? Вы же спрашивали насчёт наиболее оптимального способа? Или нет?

Вопрос про конкретную реализацию. Каковая состоит из моего софта и чужого стека.

И если меня латентность не очень волнует, то для софтдевайса требования к латентности указаны жёсткие (хоть и несоответствующие реальному состоянию дел).

 

это просто запрет прерывания и в действительности не является критической секцией.

О как.

 

PS: Кстати - маскирование прерываний через NVIC не запрещает все прерывания. Есть ещё Systick и PendSV и другие fault-ы (если они у Вас используются).

Да, действительно.

Используется ли PendSV - Вы можете посмотреть в исходниках операционной системы, которую мы обсуждаем.

 

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

Share this post


Link to post
Share on other sites
И если меня латентность не очень волнует, то для софтдевайса требования к латентности указаны жёсткие (хоть и несоответствующие реальному состоянию дел).

Странный подход к делу. Т.е. - будет ли работать этот самый девайс в составе вашего изделия или нет - Вам фиолетово?

 

Он указан. Точнее, указано семейство, но внутри семейства они достаточно одинаковые.

Используется ли PendSV - Вы можете посмотреть в исходниках операционной системы, которую мы обсуждаем.

Может мне за Вас ещё и код написать? :smile3046:

Share this post


Link to post
Share on other sites

Я ожидал советов от авторов операционки в духе "В ядре наиболее длинные крит. секции, пожалуй, в OS::channel. Если длина устраивает - можно тупо запрещать прерывания. BASEPRI не используется, потому что ...".

А разговор "вот если бы у рыб была шерсть, то на ней были бы блохи" - повторюсь, в "общение". Спасибо.

 

 

Возвращаясь к теме.

Класс TCritSect и enable/disable _context_switch() делают __set_BASEPRI() - ноль и (0xFE <<(8 - кол-во бит приоритета)).

 

Вроде б работает...

 

Также, на мой взгляд, правильнее

INLINE void raise_context_switch() { SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; }

вместо

INLINE void raise_context_switch() { *((volatile uint32_t*)0xE000ED04) |= 0x10000000; }

ключевое отличие - просто запись вместо модификации.

Share this post


Link to post
Share on other sites
Ваше мнение, как лучше:

- обернуть эти функции в OS::TCritSect

- оставить обычную критическую секцию - они всё равно делают disable_irq()/enable_irq(), несмотря на заявление техподдержки "прерывания отключать нельзя, ни на 1 секунду, ни на 1 микросекунду"

- сделать прерывания ОС и пользовательского кода с приоритетом 5..7 и разобраться с запретом через изменение регистра BASEPRI

 

Я за второй вариант. Если они сами запрещают прерывания, то и нам можно. В коде ОС критические секции достаточно короткие, на всякий случай потестировать связь - и считать, что порядок.

 

Для полного спокойствия можно (временно) добавить в TCritSect замеры максимального времени запрета прерывания в тиках DWT. Кстати, интересно будет попробовать:)

 

Также, на мой взгляд, правильнее

INLINE void raise_context_switch() { SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; }

вместо

INLINE void raise_context_switch() { *((volatile uint32_t*)0xE000ED04) |= 0x10000000; }

ключевое отличие - просто запись вместо модификации.

 

Странно, я был уверен, что исправлял "|=" на "="... Видимо, это было в каком-то другом месте. Обязательно исправлю, спасибо.

Share this post


Link to post
Share on other sites

Прошу прощения за вероятный оффтоп...

В последней (15-й) версии nRF52 SDK появилась симпатичная примочка: task manager. Скромная (есть только task и event), но экстремально легкая. Под спектр задач, которй я могу представить себе для, например nRF52832, вполне годится.

Share this post


Link to post
Share on other sites
On 8/3/2018 at 3:39 PM, esaulenka said:

Коллега sevstels, к сожалению, забил на требование нордика "никогда не отключайте прерывания при работе softdevice'а".

А может, он и не использовал софтдевайс - в примере нет, в сообщениях на форуме "все дураки, я свой велосипед строю"...

Только увидел сообщение.

Вы батенька зря "волну не гоните"...

В моем примере и не предусматривалось использование стека от Нордика, поэтому мне было не интересно, что их индусы написали в "рекомендациях". А не нужен их стек по причине ущербности, не работает он с многими моделями тлф в отличии от моего самопального. Добиться от них исправлений ошибок так и не удалось.  Если бы Вам тема была интересна, мой мылоадрес в порте был указан.

 

 

Edited by Gradient

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now