На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Перед отправкой сообщения внимательно прочтите правила раздела!!!
1. Запрещается обсуждать написание вирусов, троянов и других вредоносных программ!
2. Помните, что у нас есть FAQ раздела Assembler и Полезные ссылки. Посмотрите, возможно, там уже имеется решение вашего вопроса.

3. Настоятельно рекомендуем обратить особое внимание на правила форума, которые нарушаются чаще всего:
  3.1. Заголовок темы должен кратко отражать её суть. Темы с заголовками типа "Срочно помогите!" или "Ассемблер" будут отправляться в Корзину для мусора.
  3.2. Исходники программ обязательно выделяйте тегами [code]...[/code] (одиночные инструкции можно не выделять).
  3.3. Нежелательно поднимать старые темы (не обновлявшиеся более года) без веской на то причины.

Не забывайте также про главные Правила форума!

Добро пожаловать и приятного вам общения!!! ;)
 
Модераторы: Jin X, Qraizer
Страницы: (51) « Первая ... 24 25 [26] 27 28 ...  50 51  ( Перейти к последнему сообщению )  
> Желающим USB под ДОС , Welcome!!!
    Цитата Boogerman @
    Мы же можем эту структуру заполнять под какими угодно именами и какими угодно чиселками, откуда хост знает, что нужно читать вот именно эти? Вроде ни адресов ни ссылок на них не даем, кроме адресов на элементы массива данных. Это мой самый страшный тупняк.

    Контроллеру указывается физический адрес адрес таблицы FrameList - через порт Base+8. FrameList - это таблица из 1024 32-битных адресов заголовков очередей (QH). Она должна быть выровнена по границе 4 Кб - таким образом, она занимает целую физическую страницу, поскольку сама имеет размер 4 Кб. Контроллер при работе сканирует эту таблицу с частотой 1 заголовок за 1 микросекунду и выполняет все готовые очереди, которые встретит. Вся эта таблица в простейшем случае может указывать на один-единственный заголовок очереди (все адреса в таблице равны). Если в этом заголовке установить значени element=1 и next=3, то контроллер будет считать эту очередь пустой и реально ничего не будет делать, кроме этого самого сканирования. Когда нам нужно выполнить операцию, мы готовим очередь TD, причем в каждом TD будет указатель на следующий TD в очереди. И после того, как очередь готова, мы устанавливаем значение element в QH равным физическому адресу первого TD. В следующую микросекунду контроллер поймет, что очередь не пуста, и начнет ее выполнять.
    В более общем случае поля таблицы FrameList могу указывать на разные очереди, в том числе и очереди для обслуживания конечных точек типа Interrupt. Вот тут кстати об интерраптах - в дескрипторе конечой точки типа "интеррапт" указывается периодичность ее опроса, и мы можем в FrameList поставить ссылку на очередь для этой конечной точки так, чтобы она и опрашивалась с нужной периодичностью. Например, если там написано 2 микросекунды, то мы в каждый второй элемент FrameList записываем адрес этой очереди TD для этой конечной точки.

    Добавлено
    Блин, конечно речь идет не о микро-, а о миллисекундах! Ошибся, но вовремя исправился.
      Так, Благодарю. Сейчас поковыряюсь в мануалах еще раз на основе рассказанных Вами связей, дабы наконец слить это воедино.

      А по поводу кода? У кого-нибудь нашлось чуть свободного времени пролистать мою ахинею?
        От себя добавлю: в TD Token есть 19й бит D (триггер данных). Триггер данных ведется для каждой конечной точки, после сброса устройства в первом TD он должен быть нулевой. Далее в каждом последующем TD для этой КТ, он инвертируется т.е. 0,1,0,1... (триггер - это самые распространенные грабли :) ). Обращаю внимание на бит 2 (Vf) в указателе на следующий элемент в TD. Если он равен 0, то идет обработка в ширину т. е. при самой простой схеме (один QH), контроллер возьмет один элемент из списка и будет дожидаться конца кадра. Это были мои грабли, на самом деле все будет работать, просто медленно. Перед инициализацией контроллера лучше сделать глобальный сброс, при этом также сбросятся и все подключенные устройства. Попробуйте для начала попытаться считать дескриптор устройства. После сброса устройство имеет нулевой адрес.
          А вот у меня еще один такой вопрос, правда, мне кажется его нужно не сюда задавать.

          При приеме данных на компьютер тут все понятно, данные последовательно записываются в память с соответствующим сдвигом адреса в указателе.

          А вот со стороны МК есть такие строки:

          ExpandedWrap disabled
            bmRequestType = Usb_read_byte();
            bmRequest     = Usb_read_byte();
            ...
            ...
            string_type     = Usb_read_byte();        /* read LSB of wValue    */
            descriptor_type = Usb_read_byte();        /* read MSB of wValue    */
             
            Где  #define Usb_read_byte()  (UEDATX)


          То есть переменной присваивается значение в буфере данных регистра USB интерфейса микроконтроллера. Но он же всего 1 и вроде как никуда не записывается, так же не сбрасываются управляющие биты на получение новых данных или очистку от старых. Считывание идет подряд, а ведь частоты работы МК и скорость передачи USB разная. Почему контроллер не считывает к примеру одни и те же данные, потому что они еще не успели обновиться, или не считывает нулевые потому что еще не успели заполниться?
            Цитата Boogerman @
            А вот у меня еще один такой вопрос, правда, мне кажется его нужно не сюда задавать.

            Тут надо читать про архитектуру конкретного МК и про то, как он работает с памятью и с USB. И вообще, что подразумевается под макросом Usb_read_byte. Вполне возможно, что в нем аппаратно реализовано ожидание приема и сброс после чтения. Я программировал кое-что на стороне устройства, но это был микроконтроллер C8051 фирмы SiLabs. Как я понял, у каждого МК свои особенности.
              Я пишу для ehci, функции и читаю у него в регистрах количество портов, количество помошников и их количества портов, потом читаю статус этих портов со смещением 44h+caplen+basadr в регистре 32битном.
              Вопрос такой, для того чтобы в этих регистрах появилась скорость устройства или вообщё как понять, что это мышка или флешка или вебкамера.
                Скорость устройства определяется после подачи сигнала "сброс" на порт. А тип устройства - после чтения дескриптора.
                  Цитата zakharo @
                  Скорость устройства определяется после подачи сигнала "сброс" на порт. А тип устройства - после чтения дескриптора.

                  Понятно, спасибо, а как дескриптор прочитать, я когда флешку или мышку вынимаю из юсб то там статус меняется при моём обновлении баз сброса(правдо на другой машине нет), но там статус не полный, нужно как вы сказали сбрасывать, а какой объём памяти нужно для Next Asynchronous List Address? Для Frame List Base Address я забиваю 114688 например, и 1024*4 байт считаю занятыми.
                  Сразу вопрос какой нибудь простенькой транзакции для флешки или мышки знаете, а то устройства вижу а поговорить ещё не получается пока.
                    Чтоб прочитать дескриптор устройства, надо уже уметь делать транзакции. Хост выдает запрос Get Descriptor, устройство отвечает. Все это подробно описано в литературе, например, у того же Кулакова. Здесь пересказывать вряд ли стОит..
                    Насчет сброса порта я, наверное, неправильно выразился. Я имел в виду Reset. После окончания reset'а в статусе порта устанавливаются биты, показывающие скорость - low speed, или full speed, или high speed. Это тоже все описано в литературе и в описании контроллеров.
                      Попробую отладить с ресетом работу, по транзакции не доконца понял как с Frame List Base Address быть
                        Я сейчас точно не помню - все материалы у меня наработе. Но помнится, что работа с FrameList актуальна для UHCI. Там без него никуда. В OHCI и EHCI простые транзакции типа Control и Bulk производятся без всякого FrameList.
                        Что же касается скорости устройства - то могу немного уточнить. В контроллерах 1.1 (UHCI и OHCI) скорость устройства указывается в статусе порта сразу при подключении - она определяется по тому, какая шина (D+ или D-) подтянута к питанию. В контроллере EHCI low-speed устройства тоже определяются сразу. А вот full-speed и high-speed при подключении не различаются - контроллер показывает full-speed на оба типа. Различаются они только после ресета порта - контроллер выдает т.н. high-speed reset (как-то там начинает "звенеть" шинами D+ и D-) и смотрит на реакцию устройства. Так прописано в спецификации USB.
                          Цитата zakharo @
                          Я сейчас точно не помню - все материалы у меня наработе. Но помнится, что работа с FrameList актуальна для UHCI. Там без него никуда. В OHCI и EHCI простые транзакции типа Control и Bulk производятся без всякого FrameList.
                          Что же касается скорости устройства - то могу немного уточнить. В контроллерах 1.1 (UHCI и OHCI) скорость устройства указывается в статусе порта сразу при подключении - она определяется по тому, какая шина (D+ или D-) подтянута к питанию. В контроллере EHCI low-speed устройства тоже определяются сразу. А вот full-speed и high-speed при подключении не различаются - контроллер показывает full-speed на оба типа. Различаются они только после ресета порта - контроллер выдает т.н. high-speed reset (как-то там начинает "звенеть" шинами D+ и D-) и смотрит на реакцию устройства. Так прописано в спецификации USB.

                          У меня на одном буке 2 еши и на каждом 2 оши с 3 портами у каждого и 6 портов у еши в итоге пишется, они все хорошо меняются когда что то вставляю в разъём. На втором два еши у них по 3 порта без помощников но там не меняется статус ещё, видимо настроены по разному. Я смотрел код для юсб в ТАТОС(ось на асме) там работа с еши и уши и Next Asynchronous List Address используют, а Frame List Base Address нет (пишет, что он нужен для мышки, а мышка там поддерживается тока от уши, для оши там тоже поддержки небыло). Asynchronous List это для кольцевой работы но я ещё не понял как, для Frame List хоть понятно какого объёма память, там либо 256, либо 512 или 1024 элементов. Книжку читаю Шины PCI, USB и FireWire. Энциклопедия и спецификации смотрю, но еслиб ктонить в живую простыми словами как там сделать транзакцию.
                            Значит, так. Во-первых, буквосочетание 'hc' по-моему, никогда не произносилось как 'ш' - это я по поводу "еши" и т.д. Там EHCI, UHCI, OHCI.. По-русски я бы произнес, например, "ехси", хотя, наверное, правильно - "и-эйч-си-ай". Предлагаю писать все-таки латиницей - так проще будет.
                            Теперь - что касается портов и компаньонов. EHCI в принципе не умеет работать с устройствами USB 1.1 - ни с low-speed (мыши, клавиатуры), ни с full-speed (некоторые старые флешки, картридеры и т.д.). Он работает непосредственно только с high-speed устройствами (USB 2.0). Для того, чтобы все же обеспечить работу с устройствами 1.1, используется одна из двух схем - либо к EHC добавляются компаньоны типа OHC или UHC (какие именно - зависит от производителя чипсета), и тогда он, обнаружив на порту устройство USB 1.1, отдает его соответствующему компаньону, либо на порты EHC вешаются встроенные хабы, которые и выполняют преобразование скоростей. В первом случае подключение-отключение устройств сразу вызывает изменения в статусе порта, а во втором - нет, и вся работа ведется через хаб. Похоже, что на этих твоих буках как раз и представлены оба описанных мною способа.
                            Вот теперь и надо думать - с чего начинать программирование? Чтобы работать на твоем втором буке (с двумя EHCI), то, прежде чем добраться до конкретного устройства, придется сделать работу с хабами. Если на первом - то нельзя будет ограничиться программированием только EHCI, а придется еще заняться и OHCI - иначе всякие мыши и клавиатуры будут недоступны.
                            Как конкретно делать транзакции - напишу попозже, с работы.
                              Ну, попробую вкратце рассказать, как я работаю с контроллером EHCI.
                              В начале, понятное дело, надо его (их) найти. Потом отнимаю контроллер у BIOS, даю ему сигнал Reset, дожидаюсь, когда он закончит процедуру сброса, останавливаю его, запрещаю все прерывания (я ими не пользуюсь - все делаю только по опросу), обнуляю адрес Periodic List (base+caplen+18h - им я тоже не пользуюсь) и записываю физический адрес QH (Queue Header - заголовок очереди, он у меня постоянный) в регистр base+caplen+18h. Потом запускаю контроллер и перехожу к опросу портов.
                              В цикле по количеству портов:
                              - если у порта имеется управление питанием, и питание выключено, то включаю питание;
                              - если к порту подключено устройство full-speed, то выдаю на этот порт сигнал Reset и дожидаюсь окончания процедуры сброса;
                              - если после сброса в статусе порта появляется бит EHCI_PORT_ENABLE (бит 1), то подключенное устройство - high-speed, и я с ним буду работать через этот контроллер;
                              - если же подключенное устройство - low-speed или full-speed, то я отдаю этот порт компаньону.
                              Далее перехожу собственно к транзакциям. Чтоб работать с устройством, надо его пронумеровать (присвоить адрес на шине). Непронумерованное устройство может работать, но в усеченном режиме - например, оно может отвечать на запрос GetDeviceDescriptor, но из всего дескриптора выдавать только 8 байтов. Тут уже дело вкуса - можно запросить эти 8 байтов у непронумерованного устройства, а потом пронумеровать, а можно нумеровать сразу. Чтобы пронумеровать устройство, надо выдать на его 0 конечную точку пакет SetAddress.
                              Собственно, тут мы подошли непосредственно к транзакциям. Чтобы произвести транзакцию (для пакета SetAddress это будет транзакция типа Control), надо заполнить TD и QH согласно описанию EHCI, а потом выставить в регистре base+caplen+0 (регистр команд) бит EHCI_ASYNC_ENABLE (бит 4), не забывая оставить бит EHCI_START. Поскольку адрес QH я уже записал (при общем сбросе), то контроллер тут же начнет выполнять эту транзакцию. По завершении транзакции он сбросит бит QTD_ACTIVE (бит 6) в TD_TOKEN, ну а я в цикле с таймером ожидаю этого события.
                              Все дальнейшие транзакции происходят по той же схеме. Строится очередь TD (часто бывает достаточно одного TD - максимальный размер пакета для EHCI равен 512 байт, и этого уже достаточно для посекторного чтения mass-storage устройств, но, например, у компакт-дисков размер сектора равен 2048 байт, и там приходится делать 4 TD), формируется QH, и выставляется бит EHCI_ASYNC_ENABLE.
                              В общем, все..
                                Теперь то мне стало понятно, спасибо. Недопонял только как передать устройство компаньону и как работать через контроллер. Я думал, что сначало надо остановить, а потом ресет.
                                Сообщение отредактировано: StasNewOs -
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (51) « Первая ... 24 25 [26] 27 28 ...  50 51


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0990 ]   [ 15 queries used ]   [ Generated: 15.05.24, 06:25 GMT ]