Версия для печати темы
Форум разработчиков электроники ELECTRONIX.ru _ scmRTOS _ nRF52 BLE SDK (Cortex M3) SVC
Автор: ox0001 Jan 23 2017, 09:52
Здравствуйте!
кто нибудь пытался вести разработку на scmRTOS для nRF52 BLE SDK ?
Как сочетать API взаимодействия BLE стэка (прошивки) работающее по SVC вызовам ?
спасибо!
Автор: AHTOXA Jan 23 2017, 10:08
Вот тут недавно что-то проскакивало про NRF: http://electronix.ru/redirect.php?https://electronix.ru/forum/index.php?showtopic=139472.
Автор: ox0001 Jan 23 2017, 14:19
OK спасибо!
Автор: a9d Apr 7 2017, 00:16
В nRF SDK есть же примеры с FreeRTOS. Да и nRF52 это Cortex-M4F
Автор: esaulenka Aug 3 2018, 07:39
Цитата(AHTOXA @ Jan 23 2017, 13:08)
Вот тут недавно что-то проскакивало про NRF: http://electronix.ru/redirect.php?https://electronix.ru/forum/index.php?showtopic=139472.
Коллега sevstels, к сожалению, забил на требование нордика "никогда не отключайте прерывания при работе softdevice'а".
А может, он и не использовал софтдевайс - в примере нет, в сообщениях на форуме "все дураки, я свой велосипед строю"...
Цитата(a9d @ Apr 7 2017, 03:16)
В nRF SDK есть же примеры с FreeRTOS. Да и nRF52 это Cortex-M4F
Есть, да.
Надо взять порт scmRTOS от STM'ки, переписать критическую секцию, таймер (systick в nrf52 вернули обратно, но он батарейку жрёт), и отладить.
Ну и в процессе раскурить, что они с приоритетами прерываний сделали (нормального описания я не нашёл, к сожалению, только в духе "trust me, i know what i'm doing").
Наличие готового примера и грамотного человека, который это делал, процесс должно сильно ускорить. Ну да ладно, будет повод самому описать...
Автор: esaulenka Aug 8 2018, 08:43
Продолжаем.
Коллеги, у меня вопрос.
Техподдержка Nordic запрещает отключать прерывания, используемые softdevice'ом (это стек блютус, исполняемый на том же процессоре, что и пользовательский код; поставляется как единый hex с документированными точками входа).
Для организации критических секций у них предусмотрен следующий костыль:
http://electronix.ru/redirect.php?https://github.com/NordicPlayground/nrf52-ble-app-uart-long-range/blob/master/s140_nrf52840_6.0.0-6.alpha/s140_nrf52840_6.0.0-6.alpha_API/include/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
Автор: jcxz Aug 8 2018, 09:13
Цитата(esaulenka @ Aug 8 2018, 11:43)
sd_nvic_critical_region_enter(), sd_nvic_critical_region_exit()
Т.е:
- запретить все прерывания
- сохранить во временную переменную регистры заррешённых прерываний
- обнулить эти регистры (точнее, записать маску "только прерывания softdevice'а)
- разрешить прерывания
Ваше мнение, как лучше:
Я бы последовал их рекомендации, но с оптимизацией её: сохранять/обнулять не
все биты разрешения прерываний, а только
важные для данной конкретной критической секции.
Такая оптимизация позволит сэкономить и такты и байты.
Автор: esaulenka Aug 8 2018, 10:04
Не вижу особой пользы.
Как оно экономит? Уменьшается latency, но (забыл сказать) мне оно некритично. Общая скорость не растёт, размер не уменьшается.
Геморрой только добавляется, т.к. эту оптимизацию руками надо делать, и постоянно следить, чтобы из N-цати кртитических секций выбрать нужную.
Автор: jcxz Aug 8 2018, 10:47
Цитата(esaulenka @ Aug 8 2018, 13:04)
Не вижу особой пользы.
Как оно экономит? Уменьшается latency, но (забыл сказать) мне оно некритично. Общая скорость не растёт, размер не уменьшается.
В смысле "как"? Работа с одной переменной ведь проще/быстрее чем с несколькими. Не находите?
Не знаю сколько прерываний в вашем МК, но в моём сейчас их биты масок растянулись аж на 4-е 32-битных регистра. Это значит что в критической секции которая без разбора запрещает всё, надо будет все 4 регистра прочитать, сохранить и записать в них маскирующие значения. Что довольно-таки долго и в каждом таком месте требует 4 слова по 32 бита.
В то время как данная критическая секция может нужна для защиты всего от одного прерывания (только один регистр можно сохранить, одно прерывание запретить).
И если Вы говорите что латентность Вас не беспокоит, то к чему тогда вообще был вопрос? Вы же спрашивали насчёт наиболее оптимального способа? Или нет?
Цитата(esaulenka @ Aug 8 2018, 13:04)
Геморрой только добавляется, т.к. эту оптимизацию руками надо делать, и постоянно следить, чтобы из N-цати кртитических секций выбрать нужную.
Геморрой это только если без головы делать. С умом если, то достаточно написать макрос в котором на входе задаётся маска интересующих прерываний, а внутри он по этой маске всю работу и сделает.
И вообще-то в серьёзных системах там так и есть - для каждого защищаемого объекта - своя критическая секция. Например в винде. А то что Вы называете критической секцией, это просто запрет прерывания и в действительности не является критической секцией.
PS: Кстати - маскирование прерываний через NVIC не запрещает все прерывания. Есть ещё Systick и PendSV и другие fault-ы (если они у Вас используются).
Автор: esaulenka Aug 8 2018, 11:58
Цитата(jcxz @ Aug 8 2018, 13:47)
В смысле "как"? Работа с одной переменной ведь проще/быстрее чем с несколькими. Не находите?
Не знаю сколько прерываний в вашем МК,
Он указан. Точнее, указано семейство, но внутри семейства они достаточно одинаковые.
Цитата(jcxz @ Aug 8 2018, 13:47)
Что довольно-таки долго и в каждом таком месте требует 4 слова по 32 бита.
В решении "запретить всё", кстати, хранилище только одно.
Цитата(jcxz @ Aug 8 2018, 13:47)
И если Вы говорите что латентность Вас не беспокоит, то к чему тогда вообще был вопрос? Вы же спрашивали насчёт наиболее оптимального способа? Или нет?
Вопрос про конкретную реализацию. Каковая состоит из моего софта и чужого стека.
И если меня латентность не очень волнует, то для софтдевайса требования к латентности указаны жёсткие (хоть и несоответствующие реальному состоянию дел).
Цитата(jcxz @ Aug 8 2018, 13:47)
это просто запрет прерывания и в действительности не является критической секцией.
О как.
Цитата(jcxz @ Aug 8 2018, 13:47)
PS: Кстати - маскирование прерываний через NVIC не запрещает все прерывания. Есть ещё Systick и PendSV и другие fault-ы (если они у Вас используются).
Да, действительно.
Используется ли PendSV - Вы можете посмотреть в исходниках операционной системы, которую мы обсуждаем.
Вообще, очень прошу ознакомиться с обсуждаемой темой. Мне не очень интересно разговаривать о сферических конях, мне хочется запустить конкретную ОС на конкретном чипе. О конях - пожалуйста, в прекрасный раздел "общение".
Автор: jcxz Aug 8 2018, 12:26
Цитата(esaulenka @ Aug 8 2018, 14:58)
И если меня латентность не очень волнует, то для софтдевайса требования к латентности указаны жёсткие (хоть и несоответствующие реальному состоянию дел).
Странный подход к делу. Т.е. - будет ли работать этот самый девайс в составе вашего изделия или нет - Вам фиолетово?
Цитата(esaulenka @ Aug 8 2018, 14:58)
Он указан. Точнее, указано семейство, но внутри семейства они достаточно одинаковые.
Используется ли PendSV - Вы можете посмотреть в исходниках операционной системы, которую мы обсуждаем.
Может мне за Вас ещё и код написать?
Автор: esaulenka Aug 8 2018, 17:08
Я ожидал советов от авторов операционки в духе "В ядре наиболее длинные крит. секции, пожалуй, в 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; }
ключевое отличие - просто запись вместо модификации.
Автор: AHTOXA Aug 9 2018, 06:32
Цитата(esaulenka @ Aug 8 2018, 13:43)
Ваше мнение, как лучше:
- обернуть эти функции в OS::TCritSect
- оставить обычную критическую секцию - они всё равно делают disable_irq()/enable_irq(), несмотря на заявление техподдержки "прерывания отключать нельзя, ни на 1 секунду, ни на 1 микросекунду"
- сделать прерывания ОС и пользовательского кода с приоритетом 5..7 и разобраться с запретом через изменение регистра BASEPRI
Я за второй вариант. Если они сами запрещают прерывания, то и нам можно. В коде ОС критические секции достаточно короткие, на всякий случай потестировать связь - и считать, что порядок.
Для полного спокойствия можно (временно) добавить в TCritSect замеры максимального времени запрета прерывания в тиках DWT. Кстати, интересно будет попробовать
Цитата(esaulenka @ Aug 8 2018, 22:08)
Также, на мой взгляд, правильнее
INLINE void raise_context_switch() { SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; }
вместо
INLINE void raise_context_switch() { *((volatile uint32_t*)0xE000ED04) |= 0x10000000; }
ключевое отличие - просто запись вместо модификации.
Странно, я был уверен, что исправлял "|=" на "="... Видимо, это было в каком-то другом месте. Обязательно исправлю, спасибо.
Автор: Axel Aug 13 2018, 12:38
Прошу прощения за вероятный оффтоп...
В последней (15-й) версии nRF52 SDK появилась симпатичная примочка: task manager. Скромная (есть только task и event), но экстремально легкая. Под спектр задач, которй я могу представить себе для, например nRF52832, вполне годится.
Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)