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

Да как же это проверить, если функция всегда будет возвращать USB_OK?

static uint16_t cdc_DataTx (uint8_t* Buf, uint32_t Len)
{

    uint32_t i;
    //loop through buffer
    for( i = 0; i < Len; i++ )
    {
        //push data into transfer buffer
        APP_Rx_Buffer[APP_Rx_ptr_in] = Buf[i];
        //increase pointer value
        APP_Rx_ptr_in++;
        /* To avoid buffer overflow */
        if(APP_Rx_ptr_in == APP_RX_DATA_SIZE)
        {
            APP_Rx_ptr_in = 0;
        }
    }

    return USBD_OK;
}

Смотрел разные библиотеки, "говор" в них немного разный, но суть этой функции везде одна и та же

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


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

эта хрень не уменьшается по мере отправки?

APP_Rx_ptr_in ?

 

Если нет, то значит должен быть еще указатель который показывает где сейчас указатель последних отправленных данных

 

 

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


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

Возвращаюсь к проекту.

Мне удалось-таки настроить CDC на последней 5 версии KEIL и ее библиотеках. ПО упомянутой мной ранее СТАТЬЕ

Как выяснилось, отправка байтов все-таки не поспевала за командами контроллера. Ибо когда я поставил буфер 1024 байта, а отправляю единовременно по 640 байт, проблемы не возникает.

Но, сами понимаете, решение это временное. Хотелось бы знать, как мне организовать проверку, окончено ли задание по отправке пакета, можно ли направлять следующий? Как понять, свободен ли буфер? Перековырял всю библиотеку - то ли лыжи не едут... то ли я не пойму как это сделать...

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


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

Действительно, проблема оказалась временно решенной.

Как только я попытался передать большой поток данных, начались тормоза. Первые ошибки отправки посыпались примерно на 16 500 байте.

Вот как я отправляю

while(1)
{

  
        
    if (USBD_Configured (0)) {
                                        /* USB -> MCU                      */
      if (usb_rx_ch == -1) {
        usb_rx_ch = USBD_CDC_ACM_GetChar (0);
      }
      if (usb_rx_ch != -1) {

            
                
                for (j=0;j<480;j++) 
                    {
                    for (i=0;i<640;i++) 
                    {
                        sprintf(ss,"%d ",i);
                      RESULT=USBD_CDC_ACM_PutChar (0, ss[0]); // на эту хрень не обращайте внимания, это временно урезаный кусок.
                        if (RESULT==-1) 
                        {    
                          if (ERRORS==0) {ierr=i;jerr=j;}
                            ERRORS++;
                        }    
                    }
                }
            }
            if (usb_rx_ch != LF) usb_rx_ch = -1;
                        
        }  
    
    }

ierr и jerr - для контроля, когда возникает первая ошибка.

 

Так как все-таки правильно передавать данные?

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

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


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

Вроде б очевидно, что если функция не может отправить данные, надо чуть-чуть подождать, и это не ошибка, а вполне стандартная ситуация.

 

PS всегда считал, что документацию кейл содержит в порядке. Ан нет - в код повсюду добавили параметр instance, а в описании на сайте его нет.

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


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

Спасибо, я уже в принципе и сам дошел до этого, ставлю небольшую задержку между отправками каждого байта. Подобрал ее опытным путем, пытаясь получить максимальную скорость. В итоге - 307200 байт передаются примерно за секунду.

Кто-то писал, что CDC позволяет выжать 900 кбайт/сек.

Как этого добиться?

 

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


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

Чёрт, ну вот как, как до этого можно догадаться?!

Есть обратная связь, получилось положить в буфер CDC или не получилось. Почему бы ей не пользоваться?

 

Как ускорять кейловскую библиотеку, я не знаю. Подозреваю, что только выкидыванием и переписыванием.

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


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

Вроде б очевидно, что если функция не может отправить данные, надо чуть-чуть подождать

Чёрт, ну вот как, как до этого можно догадаться?!

Не надо иронизировать, а?

Я прекрасно понимаю, что нужно чуть-чуть подождать, я спрашивал, как не ждать определенное время, а четко ловить момент, когда можно еще что-то пихать. Что-то типа while(cdc_is_busy) {}

 

Как ускорять кейловскую библиотеку, я не знаю. Подозреваю, что только выкидыванием и переписыванием.

Очень странное предложение. А я думал настройками, коих великое множество.

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


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

Если USBD_CDC_ACM_PutChar () не смог сделать этот самый putchar, он вернёт -1.

Соответственно, ничего страшного не случится, если попросить его сделать это ещё раз. И ещё.

 

А настроек там немного совсем. Во всяком случае, таких, которые может крутить пользователь. Размер пакета там уже установлен в 64 байта, что ещё можно поменять, не знаю.

Как оно устроено внутри, кейл не говорит.

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


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

Про ошибки - проехали.

ПРо быстродействие - я уже где-то вычитал, что для того чтобы достичь максимума в 1.2 мбайт/с, нужно оперировать нужно массивами.

Для массивов есть спецфункция

extern int32_t USBD_CDC_ACM_WriteData (int8_t instance, const uint8_t *buf, int32_t len);

Как видите len - 32битный.

Но в настройках больше 64 байт в endpoint не ставится.

Даже если сам buf объявить больше чем на 64 байта - устройство USB не определяется.

 

Где собака порылась?

 

 

 

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

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


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

может где то в районе спецификации USB, по которой контрольная точка больше 64 байт для HS, FS устройств не допускает?

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


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

может где то в районе спецификации USB, по которой контрольная точка больше 64 байт для HS, FS устройств не допускает?

Возможно, но для HS размера пакета в настройках ставится 512 байт. И тем не менее - это тоже не 32 бит, как допускает параметр len

Это и наталкивало меня на мысль, что размер буфера - вещь аппаратная, в функцию можно пихать столько, сколько позволяет разерность len и ресурсы конкретного контроллера, а она уже сама позаботится о разбивке.

 

Кроме того, в настройках есть такой параметр: Maximum Communication Device Send Buffer Size, который выставляется до 1024 байт. СОбственно у меня он и выставлен в 1024 байт и я уже раскатал на них губу.

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

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


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

цитаты из исходников кейла:

 

* - 'Maximum Communication Device Send Buffer Size' specifies the maximum

* value for \em len in \ref USBD_CDC_ACM_WriteData

 

// <o>Maximum Communication Device Send Buffer Size

// <i>Specifies size of buffer used for sending of data to USB Host.

// <8=> 8 Bytes <16=> 16 Bytes <32=> 32 Bytes <64=> 64 Bytes

// <128=>128 Bytes <256=>256 Bytes <512=>512 Bytes <1024=>1024 Bytes

#define USBD_CDC%Instance%_SEND_BUF_SIZE 1024

 

 

Буфер, в который пишет USBD_CDC_ACM_WriteData() (ну и ваши тысячи USBD_CDC_ACM_PutChar()) организован в основной памяти контроллера, и оттуда библиотека перекладывает в контроллер USB кусочками по 64 байта.

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


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

Буфер, в который пишет USBD_CDC_ACM_WriteData() (ну и ваши тысячи USBD_CDC_ACM_PutChar()) организован в основной памяти контроллера,

 

вооооот....

Тогда почему же, если я делаю вот так

uint8_t DataOut[64];
uint8_t *pDataOut;
.....
USBD_CDC_ACM_WriteData(0,pDataOut,64);

и ставлю в первой строке DataOut[640], то при запуске USB вообще не определяется?

 

Работая кусками по 64 байта и склеивая их по 10 уже на компьютере, я все-таки получил вывод картинки со скоростью 1 кадр за 0.3 секунды (как раз примерно 900 кб/сек).

Но гложет меня этот короткий буфер.

Я пока-что искусственно генерю содержимое памяти. Сейчас вот прикручу DCMI и DMA - подозреваю что будут проблемы. Хотелось целую строку запихивать в буфер и тут же по сигналу окончания считывания строки отправлять ее по USB...

 

Максимум чего удалось добиться - uint8_t DataOut[256];

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

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


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

Максимум чего удалось добиться - uint8_t DataOut[256];

Вы бы пояснили, в ситуации, когда USB не определяется, 640 и 256 фигурируют только в размерности DataOut[], или при вызове USBD_CDC_ACM_WriteData() тоже?

 

А то сейчас можно подумать, что DataOut[] локальная переменная, для которой просто не хватает стека.

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


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

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

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

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

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

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

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

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

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

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