Перейти к содержанию
    

USB HID LPC1343

В LPC1343 есть встроенный драйвер USB HID устройства. Всё хорошо, всё работает, только есть вот одно но...

 

Процедура GetInReport, от которой идут данные в компьютер, вызывается с заданным интервалом по таймеру. То есть с определённым интервалом пакеты уходят в компьютер. Как сделать что бы репорты уходили не с определённым интервалом, а только тогда, когда мне это нужно, то есть тогда когда у меня есть данные на отправку? Так например работает мышка: двигаем - пошли пакеты, перестали двигать - пакеты не уходят. И как это организованно в других мк с USB при реализации HID?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как сделать что бы репорты уходили не с определённым интервалом, а только тогда, когда мне это нужно, то есть тогда когда у меня есть данные на отправку?

 

Именно так оно и работает. Если вы имеете данные для отправки, то вы загружаете их в буфер конечной точки, и при поступлении запроса от хоста эти данные уходят ему. Если же у вас нет данных, то вы ничего не загружаете в буфер конечной точки, и хост в ответ на свои запросы получает NAK. Вы можете только задать интенсивность прерываний (Interrupt In) от хоста в дескрипторе конечной точки прерывания, и все. Для мышей и клавиатур это значение всегда равно десяти. Аппаратный таймер внутри МК здесь не при чем. Хотя, конечно, вы можете по этому таймеру готовить очередные порции данных для отправки их хосту ...

Изменено пользователем kovigor

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да в том то и дело, что данные для отправки я кладу в массив, а не напрямую в буффер конечной точки. А если я даже туда ничео не положил то всё равно компьютеру отправляетя содержимое этого массива. То есть через фиксированный интервал всегда уходят данные. И никакого NAK видимо хосту не уходит... Как быть?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да в том то и дело, что данные для отправки я кладу в массив, а не напрямую в буффер конечной точки. А если я даже туда ничео не положил то всё равно компьютеру отправляетя содержимое этого массива. То есть через фиксированный интервал всегда уходят данные. И никакого NAK видимо хосту не уходит... Как быть?

 

Чудес не бывает. Если данные уходят хосту, то они были кем-то положены в буфер конечной точки. Кем ? Вопрос. Первый вариант - вами лично. Второй - подсистемой DMA. Возможно, в том проекте, который вы исследуете, используется DMA, и именно он перекладывает данные из вашего массива в буфер конечной точки. Одно я могу вам сказать совершенно точно. Досконально разобрать этот пример вам все же придется. А после его разбирания отпадут и подобные вопросы ...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да я уже всё досканально разобрал, всё по сто раз перечитал, но про это там ни слова. Либо там по другому нельзя и аппаратный вшитый драйвер умеет только так, либо кто бы мне подсказал, знающий кокретно по этому вопросу...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да я уже всё досканально разобрал, всё по сто раз перечитал, но про это там ни слова. Либо там по другому нельзя и аппаратный вшитый драйвер умеет только так, либо кто бы мне подсказал, знающий кокретно по этому вопросу...

 

А откуда вы знаете, какие именно данные приходят хосту ? Чем вы это проверяли ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А откуда вы знаете, какие именно данные приходят хосту ? Чем вы это проверяли ?

 

Ну как откуда? Во первых есть прога "USB Port Monitor", а во вторых это же принимает моя прога для PC.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ковырялся тоже с этим камушком.

Тут дело в другом - если хосту не ответить на запрос - то он перестанет опрашивать ваш девайс.

И еще - почему-то при использовании встроенного аппаратного HID у меня не получилось завести ядро на частоте выше 12МГц. Если обычным образом - контроллер и софт, то все нормально.

Я поступил в данном случае проще - в обработчике, который вызывается по запросу хоста на Data_In - поставил условие, если не выставлен флажок что данные готовы - отправляется 1 байт с содержимым 0.

Если готовы - то весь буфер. Буфер используется отдельный, для подготовки данных. И в GetInReport - содержимое копируется в InReport.

Еще. В 1343 - буферы на прием и отправку, насколько помню - аппаратные, т.е. если Вы ими пользуетесь в коде где-то, то по вызову функций отправки/приема (также аппаратно) - содержимое уйдет автоматически.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ковырялся тоже с этим камушком.

Тут дело в другом - если хосту не ответить на запрос - то он перестанет опрашивать ваш девайс.

И еще - почему-то при использовании встроенного аппаратного HID у меня не получилось завести ядро на частоте выше 12МГц. Если обычным образом - контроллер и софт, то все нормально.

Я поступил в данном случае проще - в обработчике, который вызывается по запросу хоста на Data_In - поставил условие, если не выставлен флажок что данные готовы - отправляется 1 байт с содержимым 0.

Если готовы - то весь буфер. Буфер используется отдельный, для подготовки данных. И в GetInReport - содержимое копируется в InReport.

Еще. В 1343 - буферы на прием и отправку, насколько помню - аппаратные, т.е. если Вы ими пользуетесь в коде где-то, то по вызову функций отправки/приема (также аппаратно) - содержимое уйдет автоматически.

 

Насколько я понимаю это дело, то если у девайса нет данных для отправки хосту, то он должен ответить хосту что у него нет данных и всё и не слать данные. И поэтому хост не перестанет опрашивать девайс. Так работает мышка, как я писал выше. Так вот как так сделать?

 

А как вы отправляете один байт с содержимым 0 ? У нас же размер репорта изначально описан и длинна его не может меняться? То есть мы не можем отправить или один байт или несколько за один раз?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Насколько я понимаю это дело, то если у девайса нет данных для отправки хосту, то он должен ответить хосту что у него нет данных и всё и не слать данные. ... Так вот как так сделать?

 

Просто не кладите ничего в буфер конечной точки. Тогда хосту вместо блока данных будет отправлен NAK ...

Изменено пользователем kovigor

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Просто не кладите ничего в буфер конечной точки. Тогда хосту вместо блока данных будет отправлен NAK ...

 

 

Так у меня и нет там как такового буффера. У меня есть массив, и если я даже его не меняю он отправляет предыдущее его содержимое.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Подниму тему...

 

Писателям этого ROM HID драйвера оторвать бы причинное место :)

Задумано хорошо, реализовано безбашенно.

Получилась игрушка. А жаль. Неплохое подспорье для экономии программной памяти и упрощения кода.

 

Проблема в том, что InReport постоянно шлет данные в комп. Когда надо и не надо... Соответственно, при при небольшом интервале поллинга и максимальном размере данных (64 байт) даже мой довольно шустрый комп грузит процессор под 6%. Т.е. отсутствует возможность ответить NAK при отсутствии данных. Что можно подкрутить? После инициализации ROM драйвера в программе доступен только обработчик прерывания USB (собственно, там все и крутится) и это единственная возможность подлезть, чтобы как то поправить ситуевину. В оригинале там просто вызывается подпрограмма обработчика из ROM. Есть мысль, что можно как то обработать прерываание InReport самостоятельно, заставить принудительно ответить NAK, если нет данных. Но "сала в голове", увы, не хватает ;) И неизвестно, что там наворотили в ROM драйверописцы (впрочем, имхо, там то же, что и в примерах HID от NXP, не использующих ROM драйвер и старадающей той же болячкой...) Может кто-либо решил эту проблему?

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Попробовал подлезть и так, и эдак.

Код в ROM не похож на тот, что идет в примерах от NXP и кейла.

Махнул рукой.

Решил, что для HID загрузчика подойдет и ROM драйвер - сильно экономит место. Даже много лишнего остается ;)

Ибо все-равно одна 4 кб страница будет отдана под загрузчик. "Кривизна" там существенно не мешает...

Ну а "прямой " HID драйвер - в LR ARM... Там все пучком - есть правильная функция "usbd_hid_get_report_trigger(0, buf, len)". И прерывание постоянно не щелкает - только когда инициирована передача данных. Цена вопроса - ~6 кбайт, но оно того стОит...

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

goodwin, подскажите, в RL-ARM стали исходники USB класть, или оно по-прежнему в виде бинарника и горки заголовков?

 

На бинарники закладываться как-то неинтересно, даже если там сам ARM свечку держал :-)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да - все в библиотеках.

 

ЗЫ:

Несколько строчек - пара десятков байт кода и все становится гораздо кузявее ;)

Program Size: Code=790 RO-data=426 RW-data=20 ZI-data=540 гораздо приятственнее чем 6 кБ кода RL.

Магическая цифирька 0x10 простительна - вряд ли ROM изменится...

Ну еще возможно надо проконтролировать в prepare_send () ушли ли предыдущие данные...

 

#define INT_IN_EP 0x10     // это бит прерывания Input Report
#define CCEMTY_INT          (0x1<<10)
#define CMD_SEL_EP_CLRI(x) (0x00400500 | ((x) << 16))

uint8_t fl_send=0; // флаг посылки данных

void WrCmd (uint32_t cmd) {
  LPC_USB->DevIntClr = CCEMTY_INT;
  LPC_USB->CmdCode = cmd;
  while ((LPC_USB->DevIntSt & CCEMTY_INT) == 0);
}

USB_IRQHandler(void)
{
uint32_t  disr;
  
  disr = LPC_USB->DevIntSt;           
   /* Device Interrupt Status */
  if ((disr & INT_IN_EP) && (!fl_send))  // тут проверим кинунуть гада или таки послать данные
  {
   LPC_USB->DevIntClr = disr & INT_IN_EP;    // сбросим флаг прерывания
   WrCmd(CMD_SEL_EP_CLRI(INT_IN_EP>>1));    // в железе тоже
  }
  else (*rom)->pUSBD->isr();

}

/*
*  Get HID Input Report -> InReport
*/
void GetInReport (uint8_t src[], uint32_t length) {   
fl_send=0; // сбросим флаг посылки данных
  // здесь делаем , что надо 
return;
}

void prepare_send (void)
{
   fl_send=1;                       // взведем флаг посылки двнных
   LPC_USB->DevIntSet|=INT_IN_EP; // взведем флаг прерывания GetInReport
}

/*
*  Set HID Output Report <- OutReport
*/
void SetOutReport (uint8_t dst[], uint32_t length) {
  // здесь делаем , что надо...
  
    prepare_send();    //  для примера тут инициируем посылку данных в ответ...
    return; 
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...