Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Передача данных по USB
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
mr.smart
Доброго Всем время суток, Друзья!

Есть интересная платка с процессором AT91SAM7S256. Только-только начал разбираться с написанием прошивок... Мигать уже умеем smile.gif
Сейчас буду разбираться с передачей данных по USB-шинке (других портов на плате нет) Сильно надеюсь на Вашу помощь. Конкретных вопросов много, поэтому решил, что проще создать одну тему, где их буду разбирать.

Вопрос для начала.
Как прописать для платы PID/VID? Никакой инфы в даташитах по процессору я не нашел. В стандартных проектах, в которых устройству должен прописывается PID - 6119, я нигде не смог найти данную строку.
Ну и правильно ли я понимаю, что если прописать PID/VID, то пока даже без настройки UDP и USART устройство будет определяться как "6119ое" ?

Всем заранее Спасибо!
toweroff
Цитата(mr.smart @ Oct 16 2010, 22:48) *
Доброго Всем время суток, Друзья!

Есть интересная платка с процессором AT91SAM7S256. Только-только начал разбираться с написанием прошивок... Мигать уже умеем smile.gif
Сейчас буду разбираться с передачей данных по USB-шинке (других портов на плате нет) Сильно надеюсь на Вашу помощь. Конкретных вопросов много, поэтому решил, что проще создать одну тему, где их буду разбирать.

Вопрос для начала.
Как прописать для платы PID/VID? Никакой инфы в даташитах по процессору я не нашел. В стандартных проектах, в которых устройству должен прописывается PID - 6119, я нигде не смог найти данную строку.
Ну и правильно ли я понимаю, что если прописать PID/VID, то пока даже без настройки UDP и USART устройство будет определяться как "6119ое" ?

Всем заранее Спасибо!

мда...
а какое отношение слова UDP и USART имеют отношение к VID/PID и USB?
mr.smart
Цитата(toweroff @ Oct 17 2010, 17:31) *
мда...
а какое отношение слова UDP и USART имеют отношение к VID/PID и USB?

Ну, мол, чтобы наладить передачу по USB (для начала хотя бы с эмуляцией COM-порта), нужно для начала сделать так чтоб драйвер просто определял устройство, а для этого в свою очередь нужно писать inf-файл, в котором прописывать PID. Я могу и ошибаться, Вы поправьте... Я для этого на этот форум и пришел.
Я понял, что действия нужно провернуть следующие:
- указываем для USB режим эмуляции СОМ (с CDC пока разбираюсь...)
- указываем PID/VID
- настраиваем USART
- настраиваем всякие clock'и и прочее.
- пишем собственно основу программки. Например:
Код
TRACE_CONFIGURE(DBGU_STANDARD, 115200, BOARD_MCK);
printf("test");

После всего этого можно подключать устройство, оно определяется как подключенное к СОМ. Ну и затем тестим его через гипертерминал, в котором должно появляться "test". Я где-то неправ?
toweroff
Здесь есть большая разница. Вы пытаетесь поднять CDC пот какой-то ОС, или ваяете "с нуля" USB поддержку для камня?
Отсюда разные вопросы и разные направления решения
sergeeff
А что примеры CDC от Atmel'a чем-то не устраивают? Там же все сделано без всяких ОС.

VID/PID вы должны прописать в дескрипторе usb устройства и такие же указать в inf файле.
Shaienn
почитайте данный топик, в котором я разбирался с USB. Первый пост - бред, а потом началось понимание.

PS не рано ли за USB?
mr.smart
Цитата(Shaienn @ Oct 18 2010, 09:31) *
PS не рано ли за USB?

А что еще остается делать? На моей плате только один usb-порт есть и всё.

Так. Используя стандартный Атмеловский пример "USB CDC serial converter" добился того, чтобы при подключении через USB устройство определялось как подключенное к COM-порту. Выдавать данные в гипертерминал получается с помощью готовенькой функции CDCDSerialDriver_Write. Считывать введенные данные получается с помощью готовенькой функции CDCDSerialDriver_Read. Но. Проблема в том, что единожды считав введенную информацию в буфер (например если ввести в гипертерминале символ "q"), буфер остается заполненным и новые символы туда не лезут, а функция CDCDSerialDriver_Write (которая выводит введенную информацию) постоянно выдает символ "q". Я так понимаю после CDCDSerialDriver_Write нужно как-то отчистить буфер. А вот как это сделать я не понимаю.

Вот код функции считывания в буфер:

Код
char USBD_Read( unsigned char    bEndpoint,
                void             *pData,
                unsigned int     dLength,
                TransferCallback fCallback,
                void             *pArgument )
{
    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
    Transfer *pTransfer = &(pEndpoint->transfer);
  
    // Return if the endpoint is not in IDLE state
    if (pEndpoint->state != UDP_ENDPOINT_IDLE) {

        return USBD_STATUS_LOCKED;
    }

    TRACE_DEBUG_WP("Read%d(%d) ", bEndpoint, dLength);
    //TRACE_ERROR_WP("Read%d(%d) ", bEndpoint, dLength);

    // Endpoint enters Receiving state
    pEndpoint->state = UDP_ENDPOINT_RECEIVING;

    // Set the transfer descriptor
    pTransfer->pData = pData;
    pTransfer->remaining = dLength;
    pTransfer->buffered = 0;
    pTransfer->transferred = 0;
    pTransfer->fCallback = fCallback;
    pTransfer->pArgument = pArgument;

#ifdef DMA
    // Test if endpoint type control
    if (AT91C_OTGHS_EPT_TYPE_CTL_EPT == (AT91C_OTGHS_EPT_TYPE & AT91C_BASE_OTGHS->OTGHS_DEVEPTCFG[bEndpoint])) {
#endif
        // Control endpoint
        // Enable endpoint IT
        AT91C_BASE_OTGHS->OTGHS_DEVIER = (1<<SHIFT_INTERUPT<<bEndpoint);
        AT91C_BASE_OTGHS->OTGHS_DEVEPTIER[bEndpoint] = AT91C_OTGHS_RXOUT;
#ifdef DMA
    }
    else {

        TRACE_DEBUG_WP("Read%d(%d) ", bEndpoint, dLength);

        // Others endpoints (not control)
        if( pTransfer->remaining > DMA_MAX_FIFO_SIZE ) {

            // Transfer the max
            pTransfer->buffered = DMA_MAX_FIFO_SIZE;    
        }
        else {
            // Transfer the good size
            pTransfer->buffered = pTransfer->remaining;
        }

        AT91C_BASE_OTGHS->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMAADDRESS = (unsigned int)(pTransfer->pData);

        // Clear unwanted interrupts
        AT91C_BASE_OTGHS->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMASTATUS;

        // Enable DMA endpoint interrupt
        AT91C_BASE_OTGHS->OTGHS_DEVIER = (1<<SHIFT_DMA<<bEndpoint);

        TRACE_DEBUG_WP("\n\r_RR:%d ", pTransfer->remaining );
        TRACE_DEBUG_WP("B:%d ", pTransfer->buffered );
        TRACE_DEBUG_WP("T:%d ", pTransfer->transferred );

        // DMA config
        AT91C_BASE_OTGHS->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMACONTROL = 0; // raz
        AT91C_BASE_OTGHS->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMACONTROL =
                             (((pTransfer->buffered<<16)&AT91C_OTGHS_BUFF_LENGTH)
                               | AT91C_OTGHS_END_TR_EN
                               | AT91C_OTGHS_END_TR_IT
                               | AT91C_OTGHS_END_B_EN
                               | AT91C_OTGHS_END_BUFFIT
                               | AT91C_OTGHS_CHANN_ENB);
    }
#endif

  return USBD_STATUS_SUCCESS;
}


Одно слово: нипонятна. Может кто-нибудь сталкивался с таким примером?
mr.smart
Эээм, прошу прощения за мой предыдущий пост с толстым кодом. Не сообразил использовать codebox, а сейчас уже вроде как нельзя отредактировать.

Ну значит я пока решил отложить вопрос с тем примером и перешел на простой Атмеловский пример BasicUSB.
Настроил CDC, разговор с платой веду через гипертерминал. Проблема осталась практически той же: при повторном использовании фун-ии write, программа зависает. Оказалось что при повторном использовании записи когда в ее финале происходит проверка на завершение передачи не приходит бит TXCOMP.
Код
//Wait for the end of transfer
while ( !(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) )
  if ( !AT91F_UDP_IsConfigured(pCdc) ) return length;
pUdp->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP);
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);


И из первого while'а программа выйти не может. В чем может быть проблема?
Shaienn
Я бы, на Вашем месте, не пилил чей-то код, а начал писать свой (подглядывая в чужой), понимая каждую строку кода и ожидаемую реакцию на нее.

Начните с инициализации UDP, прерывания от него. В обработчике прерывания поймайте AT91C_UDP_ENDBUSRES != 0 и двигайтесь дальше.
mr.smart
Цитата
Я бы, на Вашем месте, не пилил чей-то код, а начал писать свой (подглядывая в чужой), понимая каждую строку кода и ожидаемую реакцию на нее.

Начните с инициализации UDP, прерывания от него. В обработчике прерывания поймайте AT91C_UDP_ENDBUSRES != 0 и двигайтесь дальше.


Я хочу сперва разобраться с этим кодом, а потом уже писать своё.

Сейчас меня гложет невозможность передать в гипертерминал больше 1го пакета. Как я понимаю алгоритм передачи:
1) проверяем не заполнен ли TXPKTRDY в UDP_CSR.
2) заполняем UDP_FDR.
3) сообщаем что мы готовы отправлять данные, устанавливая TXPKTRDY в единицу.
4) ожидаем пока хост не вернет нам TXCOMP. (одновременно с этим, как я понимаю, он обнуляет TXPKTRDY)
5) обнуляем TXCOMP.

Мой код функции записи:

Код
AT91PS_UDP pUdp = pCdc->pUdp;
    
// проверяем, готов ли юсб к передаче
if (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) {
  return 0;
}
pUdp->UDP_FDR[AT91C_EP_IN] = 0x74; // хотим передать символ "t"
pUdp->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY; // готовы отправлять
while ( !(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) ); // ждем пока нам не вернут TXCOMP
pUdp->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP); // обнуляем TXCOMP


Символ 't' в гипертерминале появляется, но вот дождаться бита TXCOMP программа не может. В результате этот while зависает. В чем теоретически может быть проблема?
mr.smart
Затестили ту же самую программу на той же самой плате, но на другой машине с Вистой и соответственно другим драйвером usbser. Работает как надо. Бит TXCOMP приходит, когда следует.
Отсюда еще вопрос: некорректная работа с XP-шным драйвером - это просто баг XP-шного драйвера, а сама программа написана правильно, или корректная работа на Висте - это следствие того, что ее драйвер лояльнее относится к плохо написанной программе? Или может быть не в драйвере дело, а в железе?...
AlfaStar
Чувак... Понял твою проблему. Вот тебе четкий ответ. Считаю, что все дело в дровах. Переустанови их и 100% заработает. А лучше хлебни пивка и все сразу получиться! ВОт как вижу... beer.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.