STM32F103C8 Keil deneme surumunde calisacakn CDC ornek ariyorum.
Olabilir mi?
Hocam, USB CDC'yi kastediyorsanız Youtube'da örnek çok, cubeMx ile rahatça yapabilirsiniz. Ben de geçen sene Keil'de yapmıştım. Bir sorun çıkmadı.
Keilim deneme surumu. Sorun olmayacak mi?
@z kbyte sınırını aşmadıkça sorun yok hocam sadece usb zaten aşmıyor sınırı
Kendi sitesinden ücretsiz indirmiştim bir sorun yaşamadım. Deneme dediğiniz ücretli sürümü kullanıyorsunuz heralde. Bence sıkıntı olmaz
Kodlarimi kendim yazdigim icin ST nin ivir zivirlarini (CubeMX\ HAL vs vs) hic kullanmadim.
Bu nedenle CDC'yi kendi basima becerebilecegimi sanmiyorum. Ote yandan CubeMX, HAL vs de yuklemedim. Yuklemeyi de pek dusunmuyorum.
Bu sartlarda klasor icinde proje dosyasini tikladigimda derleyip calistirabilecegim bir ornek kodun linkini verebilirmisiniz?
Ben STM32F407 için sıfırdan USB kütüphanesi yazarken bu kütüphane (https://github.com/dmitrystu/libusb_stm32)den ilham almıştım. Ben class işine hiç girmedim ama adamın kütüphanesinde HID ve CDC ile ilgili bölümler de var gibi gözüküyor.
USB yazmak zor mu? UART, I2C, ADC falan bunları register seviyesinde yazıyordum ama USB denemedim hiç. USB'de farklı modlar vardı bir de. Anladığım kadarıyla zor bir protokol
Alıntı yapılan: mr.engineer - 14 Haziran 2021, 16:03:18USB yazmak zor mu?
Zor, ama aşırı zor değil. Dediğim gibi, class işine girmedim hiç, sadece endpoint'lere ham veri transferi yaptım. O yüzden class'lar ile gelen ek bir zorluk varsa bilemeyeceğim.
Sanırım en zor kısım, cihaz bilgisayara bağlandığında gerçekleşen
enumeration kısmını atlatmak. USB 2.0 resmi dokümanını iyice okuyup anlamak gerekiyor. Çok fazla ayrıntı var.
Beni en çok zorlayan şey ise STM32F407'nin OTG_FS donanımı oldu. Aslında pek çok şeyi otomatik yapacak şekilde tasarlanmış, ancak şeffaflıktan uzak ve erişimi zor bir buffer sistemi var. Dokümanda bununla ilgili konular bence yeterince açık anlatılmamış. Özellikle bir yerde - adres atamasının anlatıldığı bölüm - yapılması gereken işlemler sıralanmış ancak sıralama, USB 2.0 resmi dokümanında anlatılanın tersi. "Yanlış yazmış salaklar, bu ayrıntı gözlerinden kaçmış." demiştim. Ancak cihaz bir türlü çalışmadı. Sonunda anladım ki yanlış yazmamışlar, donanım o adımları USB 2.0 resmi dokümanındakinin tersi şeklinde gerçekleştirince çalışacak şekilde tasarlanmış.
Geliştirme sürecinde çakma Saleae lojik analizörün çok faydasını gördüm. Bu çakma klon cihaz 24 MHz örnekleme yapabiliyor ve bu da USB FS için sınır değer. Haliyle sık sık verileri kaçırıyordu. Ama hani derler ya, "Körlerin ülkesinde şaşılar kral olur" diye, işte o misal, ne olup bittiğini iyi kötü görmemi sağladı. O olmasaydı bu işin altından kalkamazdım.
Henüz el atmadım ama dokümanından anladığım kadarıyla F103, F042, F072, F303 gibi modellerde olan
FS Device isimli donanım daha az özelliğe sahip olsa da daha şeffaf bir şekilde çalışıyor ve sanırım programlanması daha kolay olurdu.
Bu arada USB kütüphanesini önce C'de yazdım. Sonra C++ ve FreeRTOS'a geçirdim. Son hali de çok içime sinmedi, daha epey bir elden geçirmem gerek ama sıra gelmedi bir türlü.
Turkiye'de kendi kendimize herhangi bir USB cihaz gelistirmek icin gerekli alt yapiyi veren herhangi bir kurs bilen var mi?
@z hocam, bu işi HAL, Cube falan kullanmadan register'lar ile yapan bizim gibi delilerin sayısı 3-5'i geçmez. Herkes CubeMX'te proje oluşturup geçiyor. Gerçi ST'nin USB kodlarının sıkıntılı olduğunu, neredeyse tüm işi kesme içinde yaptıklarını (benim C'de yazdığım ilk kod da böyle idi) ve bununla da kalmayıp kesme içinde
malloc() çağırdığını okumuştum bir yerlerde. Duyduklarım doğru mudur, hala öyle midir bilemeyeceğim.
Neyse, sonuçta USB kursuna da pek talep olacağını sanmıyorum. O yüzden, muhtemelen kurs da yoktur. "Müşteri buluruz, çok tutar" diyorsan belki bu işe girebiliriz beraber. Gerçi benim de eksiğim çok ama çalışır hallederim :)
Ben de cok tirmalayarak ST nin bir orneginden yola cikip HID RAW data transferi yapan kodlarimi gelistirdim. Yillardir pek cok projede sorunsuz kullaniyorum.
Fakat bu projede bile bazi noktalarin ayaklari havada.
Neyse;
Mevcut HID rutinlerimi ve desriptorlerimi yeni projeye aynen ekleyip
Device Desriptorde Class Code=0x02, SubClass degerini 0x00 yaptim.
Interface Descriptorde Class Code=0x02 SubClass degerini 0x02 yaptim. (CDC + Abstract Control Model)
Bu haliyle derledigimde windows Device Manager'da uzerinde unlem olan USB Serial Device donanimi bulunuyor.
Bu simdilik iyi bir haber.
HID rutinlerimde interface descriptorden hemen sonra HID desriptor geliyordu.
Simdi bu kismi da degistirmem gerekecek.
Bu dokumani izliyorum. https://cscott.net/usb_dev/data/devclass/usbcdc11.pdf
Alıntı yapılan: z - 14 Haziran 2021, 19:06:50HID rutinlerimde interface descriptorden hemen sonra HID desriptor geliyordu.
Simdi bu kismi da degistirmem gerekecek.
Interface'den sonra descriptor'ların nasıl sıralanması gerektiğinin bir kuralı var sanırım. Benim projede HID olmadığı için doğrudan Endpoint descriptor'lar geliyordu. Hatırladığım kadarıyla HID'ların descriptor'ları sayıca çok ve biraz da karışıklar. Bunların kendi aralarındaki sıralamalarının belli bir kuralı var mı acaba?
Bu arada, bazı class'larda özel ek descriptor'lar olmayabiliyor sanırım.
Mass Storage Device bu şekilde idi. Sadece 2 tane bulk endpoint yeterli oluyormuş.
Alıntı yapılan: z - 14 Haziran 2021, 19:06:50Device Desriptorde Class Code=0x02, SubClass degerini 0x00 yaptim.
Interface Descriptorde Class Code=0x02 SubClass degerini 0x02 yaptim. (CDC + Abstract Control Model)
Bildiğim kadarıyla Device Descriptor'da güncel uygulama class code'un 0x00 yapılıp class tanımlamasının sadece Interface Descriptor'da yapılması yönünde. Ben o şekilde yapıyorum. Benim Interface Descriptor'daki class code'um 0xff (vendor specific class) oluyor tabi.
Evet hatirladim. Device Decriptorde class codu 0x00 yapinca da 0x02 deki gibi calisiyor.
USB rutinleri ile ilgilenmeyeli yillar yillar oldu. O zaman bir program indirmis ve USB hattan gidip gelen datalari yakaliyordum ve hata yakalamada cok isime yariyordu. PIC projede bir yerlere yazmisimdir ama hatirlamiyorum. 1 aylik deneme suresi vardi.
Bu amacla hangi programi kullaniyorsun?
O tür bir program aradım ama ücretsiz olan bir şey bulamadım. Ayrıca genelde Linux üzerinde çalıştığım için seçenekler de azalıyor.
Windows tarafında "USB Sniffer" gibi bir ismi olan, ikonu da ünlü beyaz köpek (Snoopy) olan .exe dosyası şeklinde bir program vardı. Yıllar önce denk gelmiştim. Bir de WireShark'ın eklentileri ile USB gözlemlemek mümkün oluyordu galiba. Uğraşmış ama başaramamıştım. Nerede sorun çıktığını hatırlamıyorum.
Geliştirme sürecini zor da olsa tamamen klon Saleae analizörü ile atlattım. Kendi yazılımları USB FS analiz edebiliyor. Enumeration kısmını atlattıktan sonra pek ihtiyaç kalmıyor zaten. Örnekleme hızı 24 MHz değil de 50+ falan olsa USB FS için yeterli aslında.
Normalde bu iş için profesyonel cihazlar da var. Özellikle USB HS ve tabi USB 3+ için şart. Hattın arasına girip paketleri grafiksel olarak gösteriyorlar. Fiyatları epey uçuk ama ciddi bir iş için bence gerekliler.
Ekleme: Yukarıda bahsettiğim programın adı SnoopyPro (https://www.darknet.org.uk/2015/02/snoopypro-windows-usb-sniffer-tool/) imiş. Windows XP için yazılmış.
Kullandigim programin adi Usblyzer imis.
Indirdim ve hatalarimi gordum.
HID rutinlerini yazarken descriptorlerimin boyu 64 bytedan kucuk iken orjinal program 64 bytedan daha buyuk datalari yollamak icin yazilmisti.
Ben de en fazla 64 byte descriptorler var niye boyle yapmislar deyip tirpanlamis ve 64 byte yollayacak hale getirmistim.
Simdi bu duzenleme basima dert oldu. Zira CDC config descriptor 64 bytedan daha uzun.
Evet, 64'ün üzerine çıkınca birden fazla paket olması gerekiyor.
F407'nin OTG_FS donanımı bunu otomatik halledebiliyor, tek seferde 7 (galiba) pakete kadar buffer'a yerleştirmek mümkün, sırası geldikçe kendisi otomatik gönderiyor.
Ancak benim projede 4 kB'lık transaction'lar yapmam gerekiyordu. Haliyle yazılım ile buffer eklemem gerekti. Donanım buffer'ında 7*64'ten fazla yerim vardı aslında. Ama Reference Manual'de o "maksimum 7 paket" kısmını küçük bir parantez içine yazıp iyice sakladıkları için uzunca bir süre buffer'da yerim olmasına rağmen neden belli bir boyuttan fazla transaction yapamadığımı arayıp durdum.
Hatırladığım kadarıyla STM32F103 FS_Device donanımında sadece 1 paket donanım buffer'ına yazılabiliyor. Bulk ve Isochronous transferler için ise double buffer desteği var.
Bir de kısa mesaj durumuna dikkat etmek lazım. Bilgisayarın talep ettiğinden daha az miktarda veri gönderilebilir. Ancak eksik gönderilen verinin toplam boyutu 64'ün katı ise, ardından bir de zero-length-package (ZLP) göndermek gerekiyor. Yoksa bilgisayar timeout'a düşene kadar sürekli sorgu atmaya devam edebilir.
Calisan bir CDC ornegini komple klasor olarak ziplayip proje olarak verecek yok mu?
Karanlık çağlarda, bir kütüphane yada framework vs kullanmadığım dönemlerde, pic 18f2550 ile yapmak istediğim bir cihaz için https://www.beyondlogic.org/usbnutshell/usb1.shtml dan çok yararlanmış, sonrasında jan exelson un kitabını almıştım.
Alıntı yapılan: z - 15 Haziran 2021, 00:37:32Calisan bir CDC ornegini komple klasor olarak ziplayip proje olarak verecek yok mu?
@z hocam buyrun https://wetransfer.com/downloads/b48a268345d4944a67ca1ede7f5e968920210617151944/27d0c634e1eb63dae22178bf88626d2420210617151956/001197
usbd_cdc_if.c dosyasında
__weak void USB_CDC_ReceiveCpltCallback(uint8_t *Buf, uint32_t Length)
{
}
weak fonksiyonu ekledim callback olarak kullanmak isterseniz
CubeMX ile 5 dakikada hallettim.
Ama icim hic rahat degil.
Alıntı yapılan: z - 18 Haziran 2021, 17:46:42CubeMX ile 5 dakikada hallettim.
Ama icim hic rahat degil.
Evet hocam bence de abdest alıp tövbe etmelisin acilen.
Yetmezzzz. Hacca da gidecem.
Atı alan Üsküdar'ı geçiyor.
Ama
@z sırat köprüsünü geçmeye çalışıyor ;)
PC, USB cihazimdan Device Qualifier Desriptor istiyor fakat buna ne cevabi verecegimi anlayamadim.
Cihazim USB 2.00 tanimli.
Aklımda yanlış kalmadıysa, control endpoint'i STALL yapıp "O da neymiş? Ben desteklemiyorum öyle şeyleri." mesajı gönderebilirsin.
Alternatif olarak, eğer cihazında zaten high speed desteği yoksa, cihazını USB 1.1 olarak gösterebilirsin. O zaman zaten bilgisayar o descriptor'u hiç sormuyor.
CDC desriptorlerini ST Cube MX deki ornegin aynisi yaptim. Bu sartlarda enumeration yapiliyor ve device managerda cihazim com port olarak gorunuyor. Fakat uzerinde unlem isareti var.
Aciklamasinda This device can not start (Code 10) uyarisi var.
Wireshark ve USBlizer ilegelen sorgulari ve usb cihazlari verdikleri cevaplara baktigimda CubeMX kodlarinin verdigi cevapla ayni cevaplarin verildigini goruyorum.
Hangi sorgular gelmis baktigimda ip ucu olacaksa setup paket icerikleri asagida
86 06 00 01 00 00 40 00 Device Desriptoru istemis
00 05 06 00 00 00 00 00 6 nolu ardesi atamis
86 06 00 01 00 00 12 00 Device Desriptorumu istemis
86 06 00 02 00 00 FF 00 Config descriptoru istemis
86 06 03 03 09 04 FF 00 String descriptoru istemis
86 06 00 03 00 00 FF 00 String descriptoru istemis
86 06 02 03 09 04 FF 00 String descriptoru istemis
86 06 00 01 00 00 12 00 Device Desriptoru istemis
86 06 00 02 00 00 09 00 Config descriptoru istemis
86 06 00 02 00 00 43 00 Config descriptoru istemis (CDC ile ilgili ne var ne yok hepsini istemis)
86 06 00 02 00 00 09 01 Config descriptoru istemis ama wlength degerinin 0x0109 olmasi kafa karistirici
Baska da istek gelmiyor.
0x109 eger data boyu olarak yorumlayacaksak bende 265 byte veri yok. Yok bunu 9 byte veri boyu ve 0x01 parametresi olarak yorumlayacaksak bu 0x01 ne anlama geliyor bilmiyorum.
Kodlarimda talep edilen descriptor uzunluklarini 16 bit okumam gerekirken 8 byte okumusum.
Bu hatayi giderdigimde windows usb cihazimi COM olarak gordu.
265 byte da, toplamadim ama config desriptorden itibaren ne var ne yok (string desriptorler dahil toplam uzunluk) gibi gorunuyor.
265 byte yolladim sorun duzeldi cunku. Soru sormama neden olan durumda 0x109 u 0x09 olarak ele alip sadece config desriptoru yollamamdan kaynaklaniyormus. Sans iste 9 rakami config desriptorun boyu.
Toplam boy 0x108 falan olsaydi hatayi yakalamam daha kolay olacakmis.
PC tarafindan yapilan standart istekler cevapladiktan sonra USB cihaz PC tarafindan taniniyor ve kuruluyor.
Simdi PC Class'a yonelik isteklerde bulunmaya basladi.
Gelen talep asagidaki gibi
bmRequest Type: 0xA1
bmRequest 0x21
wValueL 0x00
wValueH 0x00
wIndexL 0x00
wIndexH 0x00
wLength 0x07
Bu talebin ne anlama geldigini bilmek istiyorum.
Talep edilen Standart istekler tablo halinde duyurulmus.
Ancak Class'a yonelik istekler icin tablo bulamadim.
Su anda ugrastigim Class Communication Class olduguna gore https://cscott.net/usb_dev/data/devclass/usbcdc11.pdf dokumaninda olmasi lazim.
Acaba burdaki sorgu 16.sayfadaki GET_LINE_CODING mi oluyor?
https://www.silabs.com/documents/public/application-notes/AN758.pdf
2. sayfada aradigim cevabi buldum fakat bu tip bilgilere 3. parti kaynaklardan degil de USB kurulusunun kendi dokumanlarindan ulasabilmek lazim.
0x20 = SET_LINE_CODING
0x21 = GET_LINE_CODING
0x22 = SET_CONTROL_LINE_STATE
Bir ara bu CDC ile seri port meselesini ben de araştırmıştım ama derli toplu güzel bir doküman bulamadım. Bir ihtimal, bu konuda kesin bir standart olmayabilir. Çünkü düşünsene, bilgisayara bağladığın çipin markasına ve modeline göre (FTDI, Prolific, CH340G vs.) ayrı sürücüler yüklenmesi gerekiyor. Eğer hepsi aynı şekilde konuşsaydı sürücü yüklemeye gerek kalmazdı bence.
Bir de ACM diye bir şey var. Tam ne olduğunu çözemedim ama konu ile ilgili bir gözüküyor. Sanki bir çeşit standart sanal seri port protokolü gibi. Eğer bilgisayar tarafından varsayılan olarak destekleniyorsa buna odaklanmak mantıklı olabilir.
CDC icin surucu gerekmiyor. Eger cihaz Vendor spesific olursa gerekiyordur.
ACM ile su siralar ugrasiyorum zaten.
Bilgilerim netlesince aciklarim.
Su anda ugrastigim CDC de PID ve VID ST nin kendi orneklerindeki degerleriydi. Bunlari 0 ve 5 yaptim. Boylelikle PC kullandigim cipin ST olup olmadigini artik bilmiyor. Fakat CDC hala sistem tarafindan taniniyor.
HOST, Interface desriptoru istediginde interface'in CDC sinifi oldugunu ogrendiginde, SubClass'in da ACM (Abstract Control Model) oldugunu ogrendiginde, protokolun de AT command oldugunu ogrendiginde driver falan istemeden seri iletisim yapabiliyor.
Dolayisi ile hangi cipi kullanirsaniz kullanin, yapiyi bu sekilde kurarsaniz driver ihtiyaci ortadan kalkiyor.
Durum bunu gosteriyor ama kesin bilgi degil bu.
Su anda PC, baud rate, parity, stopbit vs vs degistirebiliyor, yada tersine set edilmis degerleri okuyabiliyor. Henuz data alma gonderme yok. Su haliye program 3752 Byte yer kapladi. 4 K dan daha az bir kod alaninda bu is bitecek.
Simdiki sorunum biraz ilginc.
CDC cihazim windows tarafindan Com15 olarak gorunuyor.
Echo 12345>Com15 dedigimde HDD'de Com15 adinda bir dosya olusturup icine 12345 yaziyor.
Halbuki 12345 verilerinin Com15 portuna yonlenmesi lazim.
Yorum yapacak var mi?
Windows'ta oluyor mu ki öyle şeyler?
Ben de anlamadim. Com reserve edilmis kelimelerden.
echo xxxx>COMn
n=1..9'a kadar kiziyor 10 ve ustune kizmiyor ve dosya olusturuyor.
Benim cihazin com numarasi da 15 olunca terslik oluyor.
ST nin CDC ornegini inceleyip kendi yazilimimi olusturmustum.
Simdi bu yazilimi biraz daha basitlestirmeye calisiyorum.
Bir sey dikkatimi cekti.
EP0 In ve Out zaten kontrol transferi icin kullaniliyor.
Descriptor tablolarinda proje icin 3 tane End Point kullanilacagi belirtilmis.
ST bunlara Ep1, Ep2 ve Ep3 demis.
End Pointlerler icin 0x82, 0x81 ve 0x03 kullanmis.
0x01, 0x81 ve 0x82 varken neden boyle yapmis anlamadim.
ST islemcide her bir endpoint numarasi hem in hem out olabiliyor.
Yani 0 nolu endpoint control icin kullanilirken buraya PC den gelen sorgular geliyor ve gene 0 dan cevap verebiliyoruz.
Ayni sekilde EP1 hem in hem out olabiliyor.
8 tane EndPoint registerimiz var. Bu bizim 16 endpointimiz oldugu anlamina gelmiyor mu?
hocam neyin pesindesin bilmiyorum ama eski bir hid uygulamamin usbconf dosyasinda bu sekilde tanimlamis belki isine yarar
/**
******************************************************************************
* @file usbd_conf.h
* @author MCD Application Team
* @version V1.0.0
* @date 19-September-2011
* @brief USB Device configuration file
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CONF__H__
#define __USBD_CONF__H__
/* Includes ------------------------------------------------------------------*/
#include "stm32f4_discovery.h"
/** @defgroup USB_CONF_Exported_Defines
* @{
*/
#define USBD_CFG_MAX_NUM 1
#define USBD_ITF_MAX_NUM 1
#define USB_MAX_STR_DESC_SIZ 64
#define USBD_DYNAMIC_DESCRIPTOR_CHANGE_ENABLED
/** @defgroup USB_String_Descriptors
* @{
*/
/** @defgroup USB_HID_Class_Layer_Parameter
* @{
*/
#define HID_IN_EP 0x81
#define HID_OUT_EP 0x01
#define HID_IN_PACKET 64
#define HID_OUT_PACKET 64
/**
* @}
*/
/** @defgroup USB_CONF_Exported_Types
* @{
*/
/**
* @}
*/
/** @defgroup USB_CONF_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USB_CONF_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USB_CONF_Exported_FunctionsPrototype
* @{
*/
/**
* @}
*/
#endif //__USBD_CONF__H__
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
USB organizasyonunun tanimladigi End Pointlerle STM32 nin USB End Point registerlerinin numaralandirilmasi arasinda kafa karisikligim var.
USB-IF endpoint numarası tanımlamaz. Sadece mesela der ki "Mass storage class'ı için 1 adet Bulk-OUT, bir adet de Bulk-IN gerekiyor". Sen istediğin numaraları kullanırsın. İster EP1-OUT ile EP1-IN kullan, ister EP2-IN ile EP4-OUT kullan, keyfine kalmış. Interface descriptor'ında hangi endpointleri kullandığını listeliyorsun zaten.
Evet dedigin gibi mevcut uygulamada gereksiz EP registerleri kaldirip zaten sadece in olanlarin outlari yada tersini yaparak daha az RP Reg kullanarak CDC uygulamami calistirdim.
Henuz denemedim ama Ep1, Ep2 gibi reglere ayrica sen su ep sin gibi tanim yapilabiliyor. Ben Ep1 e sen End Point 1 sin 2 isen End Point 2 sin yaziyordum. Bunlari da mesela Ep1 Regin en dusuk bit alanina 2 yazarsak sen Ep1 regsin ama EndPoint 2 sin diyebiliriz. Bunu da ilk firsatta deneyecegim.