‮Сдвиг по фазе (kincajou) wrote,
‮Сдвиг по фазе
kincajou

Categories:

CC2564B, странные странности

Чувствую себя настоящим хакером, ибо чем дальше разбираюсь - тем меньше понимаю.

Итак, что сделано и что найдено.

1) написал скелет протокола. В настоящее время он выглядит как конечный автомат, управляющий состояниями других, вложенных в него, конечных автоматов (пока что их три - генератор команд, обработчик событий и обработчик ошибок).
1.1) Команды объединены в список списков или, скорее, в хэш-таблицу хэш-таблиц -- поиск по спискам идёт на соответствие ключа с образцом: на первом уровне образец это поле OGF (OpCode Group Field), а возвращаемое значение - список кодов OCF (OpCode Command Field); на втором уровне вложенности поиск идёт по OCF, а возвращаются связанные с ключами структуры, содержащие указатель на функцию-разборщик ответных данных (если они подразумеваются), шаблон аргументов для генератора бинарных данных и константный указатель на текстовое описание, уже чисто для красоты. Такая фигота нужна для того, чтобы хоть немного ускорить и упорядочить поиск по этим таблицам. Сам список составлен при помощи макросов с фиксированным списком параметров, разворачивающих в ещё один общий макрос, уже с переменным количеством параметров. Это сделано для того, чтобы простыми средствами, ещё на этапе компиляции, отловить передачу неправильного количества аргументов (ибо функция-генератор одна на всех и как раз ей-то вышеуказанный шаблон передаётся -- при этом проверить, соответствует ли количество аргументов шаблону, довольно трудно. Стандартная библиотека делает это для printf/scanf каким-то грязным приёмом, я так не умею и уметь НЕ хочу).

1.2) функция-разборщик нужна для события Command_Complete - когда оно приходит, оно содержит ответ на некую предыдущую команду ("некую" потому, что вовсе не факт, что она по факту была предыдущей - ответ может прийти довольно поздно, если обработка заняла какое-то время. Скажем, если мы подадим команду HCI_Inquiry, а затем HCI_Read_BD_ADDR, то сначала получим Command_Complete для HCI_Read_BD_ADDR, а сильно потом, через сколько-то секунд, придёт Command_Complete для HCI_Inquiry. Поэтому надеяться на то, что ответы всегда во времени сцеплены с запросами, нельзя). Все эти обработчики построены по одной и той же схеме, но с разной начинкой: принимая указатель кусок бинарных данных, функция разбирает его в соответствии со строго определённым для данного события и данной команды шаблоном, анализирует полученные данные восемнадцать тридцать восемь и сигнализирует наружу, как-то там меняя состояние системы (побочные эффекты, передача сообщений и прочий шлак в полный рост!). Вынести наружу описания этих шаблонов, наверное, можно, но я не смог придумать удобный способ, как это сделать (всё равно у всех обработчиков "кишки" разные, так что тут никакого выигрыша уже нет)

1.3) Обработка событий организована аналогично: хэш-таблица с ключом Event_Code и структурами, содержащими указатели на функции-обработчики (и вот тут тоже ничё не поделать - как не выкручивайся, но всё равно надо нагенерить мильён этих самых обработчиков, совершенно по-разному устроенных для каждого их событий) и текстовое описание.

1.4) Обработчики ошибок.. в общем, всё то же самое :) благо табличка с кодами ошибок едина для всех команд и событий.

2) Протокол уже кой-как подёргивается и подпрыгивает на месте, высылая простые, но вполне осмысленные команды и даже получая какие-то на них ответы.

3) Однако, не без сюрпризов. Выяснилось, что
3.1) после включения питания и подачи сигнала сброса, разумеется, микросхеме требуется заливка прошивки с каким-то секретным фирменным кодом. Код заранее организован в формате потока команд, так что от пользователя требуется только этот самый поток направить в чип и, если очень хочется, прочитать ответы (события Command_Complete). Этот этап проходит вполне успешно, но
3.2) после завершения процедуры заливки, чип вроде как полностью готов к работе... однако, это не совсем так - микросхема какое-то время ещё нормально принимает команды и отвечает на них, а затем словно бы зависает и больше уже ничего не происходит. Но!
3.3) если после заливки прошивки микросхему снова сбросить (физически, передёргиванием пина #Shutdown), то она вроде как прочухивается и уже более-менее внятно и правдоподобно отвечает на команды (в случае, например, HCI_Inquiry: сначала событием Command_Status, затем, если повезёт, событием Inquiry_Result, и завершает транзакцию событие Inquiry_Complete). Разумеется, в документации об этом ни слова. Кроме того, иногда после первого сброса чип может прислать событие Hardware_Error, коды каждый раз разные (то Bad_Type, то Framing_Error -- что это всё означает, в документации тоже не говорится). Однако же,
3.4) после этого второго сброса перестаёт работать команда HCI_Write_Scan_Enable (которая переводит чип в режим "видимости" так, что его наличие можно обнаружить с других bluetooth-устройств)! При этом, если чип НЕ сбрасывать после заливки, то HCI_Write_Scan_Enable отрабатывает нормально (если, конечно, успеть её выслать до зависания) -- с телефона, например, я вижу появление устройства с именем, как прописано в коде инициализации, "STM32F103+CC2564B". Но не могу к нему подключиться, потому что микросхема - увы! - "висит".
3.5) команда HCI_Reset, тащамта, не помогает ни от чего. Она разве что сбрасывает какие-то настройки, но если чип завис - он завис, помогает только переброс питания или вышеупомянутый #Shutdown.

Ситуация явно ненормальная, но где скрыт косяк, пока не ясно (чип точно работоспособен, я его подключал к Cubieboard и в линуксе через Obex получал фотографии с мобильника).
Tags: приключения Электроника
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments