|
|
|
nRF52 BLE SDK (Cortex M3) SVC |
|
|
|
Jan 23 2017, 09:52
|
Группа: Новичок
Сообщений: 2
Регистрация: 23-01-17
Пользователь №: 95 120
|
Здравствуйте!
кто нибудь пытался вести разработку на scmRTOS для nRF52 BLE SDK ?
Как сочетать API взаимодействия BLE стэка (прошивки) работающее по SVC вызовам ?
спасибо!
|
|
|
|
|
Jan 23 2017, 14:19
|
Группа: Новичок
Сообщений: 2
Регистрация: 23-01-17
Пользователь №: 95 120
|
OK спасибо!
|
|
|
|
|
Aug 3 2018, 07:39
|
Профессионал
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877
|
Цитата(AHTOXA @ Jan 23 2017, 13:08) Вот тут недавно что-то проскакивало про NRF: ссылка. Коллега 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"). Наличие готового примера и грамотного человека, который это делал, процесс должно сильно ускорить. Ну да ладно, будет повод самому описать...
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
Aug 8 2018, 08:43
|
Профессионал
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877
|
Продолжаем. Коллеги, у меня вопрос. Техподдержка Nordic запрещает отключать прерывания, используемые softdevice'ом (это стек блютус, исполняемый на том же процессоре, что и пользовательский код; поставляется как единый hex с документированными точками входа). Для организации критических секций у них предусмотрен следующий костыль: https://github.com/NordicPlayground/nrf52-b...nrf_nvic.h#L437sd_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
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
Aug 8 2018, 09:13
|
Гуру
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713
|
Цитата(esaulenka @ Aug 8 2018, 11:43) sd_nvic_critical_region_enter(), sd_nvic_critical_region_exit() Т.е: - запретить все прерывания - сохранить во временную переменную регистры заррешённых прерываний - обнулить эти регистры (точнее, записать маску "только прерывания softdevice'а) - разрешить прерывания Ваше мнение, как лучше: Я бы последовал их рекомендации, но с оптимизацией её: сохранять/обнулять не все биты разрешения прерываний, а только важные для данной конкретной критической секции. Такая оптимизация позволит сэкономить и такты и байты.
|
|
|
|
|
Aug 8 2018, 10:47
|
Гуру
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713
|
Цитата(esaulenka @ Aug 8 2018, 13:04) Не вижу особой пользы. Как оно экономит? Уменьшается latency, но (забыл сказать) мне оно некритично. Общая скорость не растёт, размер не уменьшается. В смысле "как"? Работа с одной переменной ведь проще/быстрее чем с несколькими. Не находите? Не знаю сколько прерываний в вашем МК, но в моём сейчас их биты масок растянулись аж на 4-е 32-битных регистра. Это значит что в критической секции которая без разбора запрещает всё, надо будет все 4 регистра прочитать, сохранить и записать в них маскирующие значения. Что довольно-таки долго и в каждом таком месте требует 4 слова по 32 бита. В то время как данная критическая секция может нужна для защиты всего от одного прерывания (только один регистр можно сохранить, одно прерывание запретить). И если Вы говорите что латентность Вас не беспокоит, то к чему тогда вообще был вопрос? Вы же спрашивали насчёт наиболее оптимального способа? Или нет? Цитата(esaulenka @ Aug 8 2018, 13:04) Геморрой только добавляется, т.к. эту оптимизацию руками надо делать, и постоянно следить, чтобы из N-цати кртитических секций выбрать нужную. Геморрой это только если без головы делать. С умом если, то достаточно написать макрос в котором на входе задаётся маска интересующих прерываний, а внутри он по этой маске всю работу и сделает. И вообще-то в серьёзных системах там так и есть - для каждого защищаемого объекта - своя критическая секция. Например в винде. А то что Вы называете критической секцией, это просто запрет прерывания и в действительности не является критической секцией. PS: Кстати - маскирование прерываний через NVIC не запрещает все прерывания. Есть ещё Systick и PendSV и другие fault-ы (если они у Вас используются).
|
|
|
|
|
Aug 8 2018, 11:58
|
Профессионал
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877
|
Цитата(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 - Вы можете посмотреть в исходниках операционной системы, которую мы обсуждаем. Вообще, очень прошу ознакомиться с обсуждаемой темой. Мне не очень интересно разговаривать о сферических конях, мне хочется запустить конкретную ОС на конкретном чипе. О конях - пожалуйста, в прекрасный раздел "общение".
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
Aug 9 2018, 06:32
|
фанат дивана
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684
|
Цитата(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; } ключевое отличие - просто запись вместо модификации. Странно, я был уверен, что исправлял "|=" на "="... Видимо, это было в каком-то другом месте. Обязательно исправлю, спасибо.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|