В первой статье, посвящённой nRF51822 модулю и опытов над ним я запустил на этом модуле простейшую мигалку светодиодами. Но это вовсе не то для чего создавался этот модуль и главная цель это получение полноценного BLE устройства. Поэтому продолжаю эксперименты и попробую поднять на устройстве BLE.
Для начала было бы неплохо узнать, что у нас есть на борту. Зачем это нужно станет понятно в дальнейшем, а пока поверьте мне на слово — это важно. Поэтому в начале небольшое лирическое отступление и минутка теории.
Как узнать версию текущего softdevice-а, зашитого в устройство?
Идентификатор SoftDevice находится по адресу 0x300C
. Попробуем извлечь его оттуда.
1 | $ JLinkExe -device nrf51822 -if swd |
По таблице находим что за SoftDevice соответствует этому идентификатору. Если возвращается пустое значение 0xFFFF
значит SoftDevice не установлен.
SoftDevice | FWID |
---|---|
S110 v7.1.0 | 0×005A |
S110 v8.0.0 | 0×0064 |
S120 v2.0.0 | 0×0060 |
S130 v1.0.0 | 0×0067 |
S130 0.9alpha | 0×005E |
S130 v2.0.0-7.alpha | 0×0078 |
S310 v2.0.0 | 0×005D |
S132 v1.0.0-3.alpha | 0×006D |
Более подробно тут https://devzone.nordicsemi.com/question/3629/how-do-i-access-softdevice-version-string/? answer=3693#post-id-3693
Итого как оказалось я залил softdevice S130 версии 1. Собственно с SDK v10 поставляется именно она поэтому с виду вроде как всё в порядке.
Для более глубокого погружения в тему — вот спецификация на S130 v1.0.0. Уверен, придётся туда заглядывать ещё не раз.
Тип чипа
В предыдущей статье уже упоминал важность знания конкретной маркировки чипа. В связи с этим заснял свой экземпляр:
Ниже привожу выдержки из документации по конкретно этому чипу. Моей целью было узнать подробно о распределении адресного пространства контроллера, чтобы указать эту информацию линковщику осознанно, а не тупо копипастить куски кода.
Адресация S130
Итак я нашёл как распределяется адресное пространство контроллера в случае использования SoftDevice S130 v1.
На этой схеме:
Параметр | Значение | Где найти |
---|---|---|
APP_CODE_BASE | 0×1C000 | Спецификация к SoftDevice |
APP_RAM_BASE | 0×20002800 | Спецификация к SoftDevice |
SizeOfProgMem | 256k | Определить по типу чипа |
SizeOfRAM | 16k | Определить по типу чипа |
И что же это нам даёт? А даёт это нам возможность корректно указать линковщику куда (в какие области памяти) размещать код. Softdevice передаёт управление программе по конкретному адресу, поэтому эти значения нужно указывать точно иначе код просто не запустится.
Конфигурация линкера
Чтобы упростить работу со всем этими областями памяти gcc
предоставляет нам возможность указать все эти области, а так-же расположение секций кода в специальном файле, который потом можно скормить линковщику и тот в свою очередь раскидает код как надо. В примерах SDK это файлы с расширением ld
.
Секция MEMORY
Здесь задаются значения областей памяти доступных коду программы. В нашем случае мы должны вычислить области флеша и памяти, свободные после заливки в память устройства кода softdevice. Значения по умолчанию можно найти в соответствующих файлах, расположенных в папке components/toolchain/gcc
SDK.
Выглядит это примерно так:
1 | MEMORY |
Скажем прямо — сходу ничего непонятно — какие-то константы и откуда они взялись решительно неясно.
Как рассчитать эти значения
Поля ORIGIN
берутся из спецификации к SoftDevice-у. Выше в таблицах указаны значения для S130 v1.
Для флеша
- ORIGIN = APP_CODE_BASE = 0×1C000
- LENGTH = < размер флеш памяти> — ORIGIN = 256k — 0×1C000
Для ОЗУ
- ORIGIN = APP_RAM_BASE = 0×20002800
- LENGTH = < размер ОЗУ> — (APP_RAM_BASE — 0×20000000) = 16k — 0×2800
Для ОЗУ нумерация адресов идёт не с нуля, поэтому и вычитаем начальный адрес.
Для ОЗУ так-же есть нюанс — ORIGIN
не фиксирован и в ряде случаев должен быть пересчитан, но это уже нюансы которые описаны в документации.
В итоге для XXAA
чипа и SoftDevice S130 v. 1 конфигурация памяти в файле линковщика будет выглядеть как:
1 | MEMORY |
Секция SECTIONS
Здесь задаются секции кода. В файле components/toolchain/gcc/nrf51_common.ld
(ну и соответствующие common файлы для других чипов) описаны стандартные секции кода, поэтому этот файл всегда включается в файл линковщика.
Часто встречающаяся секция fs_data
и fs_data_out
предназначена для хранения информации о привязке (bonding). Ну или для хранения любой другой информации используя API для хранилища если это вам нужно. Поэтому как правило нужна. Более подробно можно почитать в документации
Какой пример будем запускать?
Поковырявшись в примерах решил попробовать этот examples/ble_peripheral/ble_app_uart
. Не скажу почему, но с другой стороны почему бы и нет?
Итак исходный код не трогаю, ибо он мне пока не интересен — тут бы готовый пример заставить работать, а не с кодом упражняться. В папке вижу подпапку pca10028
— это какая-то демоплата, но у меня такой нет, а есть ble400
, просто копирую всю папку pca10028
в ble400
и далее буду упражняться на ней.
Заходим в неё и видим знакомые нам подпапки S110
и S130
. Очевидно нам нужна S130
ибо выше всё уже посчитано для неё. Внутри сразу проходим в armgcc
и видим знакомые нам Makefile и конфигурацию линковщика. Ну что — лопату в руки и поехали.
Правим Makefile
- Меняю имя проекта с
ble_app_uart_s130_pca10028
наble_app_uart_s130_ble400
-DBOARD_PCA10028
на-DBOARD_CUSTOM
- Добавляю
-D__HEAP_SIZE=512
к опциямCFLAGS
иASMFLAGS
Ну и собственно и всё. Последнее действие нужно т. к. при сборке выскочила ошибка region RAM overflowed with stack
. В общем уменьшение HEAP до 515 решает проблему, но я больше склоняюсь к мысли переехать на SoftDevice S110, как менее ресурсоёмкий.
Линковщик
Выше уже все расписал, поэтому просто приведу свой файл.
1 | /* Linker script to configure memory regions. */ |
Сборка
Просто выполняем команду make
1 | $ make |
То, что выходной файл имеет неверное имя чипа и его тип не должно смущать, это всего-лишь наименование которое авторы SDK видимо ленятся менять. Поэтому я тоже поленюсь и оставлю как есть. Но тем не менее мы получили файл прошивки nrf51422_xxac_s130.hex
и это прекрасно.
Прошивка
Давайте же наконец зальём наше творение в модуль и посмотрим как оно работает и работает ли вообще.
Расчехляю JLink, соединяю всё как надо и запускаю процесс прошивки. На всякий случай очищу память модуля и заново залью SoftDevice и свой код.
1 | $ JLinkExe -device nrf51822 -if swd |
Если кого-то пугают ужасные пути подскажу — в JLink-е есть автодополнение путей по клавише Tab.
На этом месте плата бодро зажгла светодиоды, что видимо что-то означает, но я не знаю что. Ну как минимум что-то сработало — теоретически у нас сейчас должно работать Bluetooth устройство. Надо бы его как-то поискать.
Результат
В итоге попробовал просканировать эфир программой «nRF Connect» и собственно увидел в списке устройств Nordic_UART
, что как бы намекает нам, что устройство функционирует и доступно для подключения.
Я считаю неплохой результат — по крайней мере ещё один шаг вперёд.
Комментарии