Das beim STM32F103 USB und CAN nicht gleichzeitig gehen ist bekannt. Die vom Pinpout gleiche STM32F303 Serie hat ein etwas anderes USB Modul und die USB-Interrupts kann man remappen damit sie nicht von CAN mitbenutzt werden. Bleibt der gemeinsam benutzte SRAM von 512byte bei den kleinen und 1024byte bei den größeren. z.B. STM32F303RB 64pin 512byte SDRAM für CAN/USB STM32F303RD(E) 64pin 1024byte SDRAM für CAN/USB Im Referenz-Manual steht im Abschnitt 32.3 (Seite 1055) 2. The STM32F303xD/E embeds a full-speed USB device peripheral compliant with the USB specification version 2.0. The USB interface implements a full-speed (12 Mbit/s) function interface with added support for USB 2.0 Link Power Management. It has software- configurable endpoint setting with packet memory up-to 1 Kbytes (256 bytes are used for CAN peripheral if enabled) and suspend/resume support. 3. When the CAN peripheral clock is enabled in the RCC_APB1ENR register, only the first 768 Bytes are available to USB while the last 256 Bytes are used by CAN. Das liest sich für mich so, dass bei den D/E Typen USB und CAN gleichzeitig benutzt werden kann, wenn ich mich bei USB mit 768byte zufrieden gebe. Was bei den Typen mit 512byte passiert bleibt offen. Die Frage ist: Hat schon mal jemand von euch USB und CAN gleichzeitig benutzt mit einem Vertreter der STM32F303 Serie?
temp schrieb: > Das liest sich für mich so, dass bei den D/E Typen USB und CAN > gleichzeitig benutzt werden kann, wenn ich mich bei USB mit 768byte > zufrieden gebe. Richtig. > Was bei den Typen mit 512byte passiert bleibt offen. Da kannst du sie nicht gleichzeitig nutzen. > Hat schon mal jemand von euch USB und CAN gleichzeitig > benutzt mit einem Vertreter der STM32F303 Serie? Irgendwer hat das hier im Forum schon gemacht und dazu berichtet, dass man den Interrupt vom USB auf eine andere Nummer um-mappen muss. Normalerweise benutzt du den Interrupt 20 (USB_LP_CAN_RX0_IRQHandler) entweder für USB oder CAN. Wenn du beide Schnittstellen gleichzeitig benutzen willst, musst du USB umkonfigurieren, so dass dieser stattdessena auf Interrupt 25 ausweicht (USB_LP_IRQHandler). Siehe Register SYSCGFG->CFGR1 Bit 5 USB_IT_RMP. Ich habe das nicht ausprobiert.
Ich hatte eine Anfrage an Olimex gemacht ob sie nicht folgendes Board: https://www.olimex.com/Products/Duino/STM32/open-source-hardware mit einer alternativen CPU ausstatten könnten, welche diese Einschränkungen nicht hat. Zuerst hatte ich es nicht für möglich gehalten, dass der STM32F303RB diese Einschränkung hat, wurde aber eines besseren belehrt. Ich hab erst mal ein Nucleo-F303RE bestellt, damit teste ich mal selbst.
So, zur Info. Ich habe das Nucleo-STM32F303RE getestet und damit gehen USB und CAN gleichzeitg.
temp schrieb: > So, zur Info. Ich habe das Nucleo-STM32F303RE getestet und damit > gehen > USB und CAN gleichzeitg. Hättest du vllt ein Beispielprojekt, was du hochladen könntest?
Das ist schwierig, weil nur Quick und Dirty zusammen gestückelt um es zu testen. Keine HAL oder STDLIB, dafür aber Codeteile die ich nicht rausgeben kann. Die einzige Besonderheit ist das Ummappen der USB-Interrupts. Alles andere ist so wie bei den anderen STM32F303 auch. Du kannst das Projekt von Stefan Frings: http://stefanfrings.de/stm32/stm32f3.html für den STM32F303RE ohne HAL benutzen um erst mal den USB-Teil zum laufen zu kriegen. Wenn du das am Laufen hast, kann ich dir gern sagen was du zum ummappen der iRQs machen musst.
Ich hab hier mal noch einen Nachtrag zu dem Beispielprojekt von Stefan das auf dem Code von WS basiert. Die Problematik mit der Nop() Implementierung und eventuellen Compileroptimierungen wurde ja an anderer Stelle schon mal besprochen. Ich hatte das mal als Projekt für Crossworks gemacht und bin immer wieder über diese Stelle gestolpert und musste nachtunen. Blöd ist auch, dass die eine entscheidende Stelle im Code am Ende der Funktion WriteControlBlock sehr häufig aufgerufen wird und da jedesmal diese Delays eingebaut werden.
1 | int WriteControlBlock(byte* PBuffer, int count) |
2 | {
|
3 | #if ENABLE_TRACING
|
4 | char buf[30]; |
5 | sprintf(buf,"wrCtrlBlock count=%i\n",count); |
6 | trace(buf); |
7 | #endif
|
8 | UMEM_FAKEWIDTH A, L; |
9 | UMEM_FAKEWIDTH* P; |
10 | int i, n; |
11 | |
12 | if (count > EpCtrlMaxLen) |
13 | count = EpCtrlMaxLen; |
14 | EpTable[0].TxCount = count; |
15 | |
16 | if (count) |
17 | {
|
18 | A = 0; |
19 | i = 0; |
20 | n = 0; |
21 | P = (UMEM_FAKEWIDTH*) EPControlTxBuffer; |
22 | while (i < count) |
23 | {
|
24 | L = *PBuffer++; |
25 | A = A | (L << n); |
26 | n += 8; |
27 | if (n > 8) |
28 | {
|
29 | n = 0; |
30 | *P++ = A; |
31 | A = 0; |
32 | }
|
33 | ++i; |
34 | }
|
35 | if (n) |
36 | *P = A; |
37 | }
|
38 | ValidateBuffer(logEpCtrl); |
39 | |
40 | // temp: Auskommentiert da nicht nötig
|
41 | // Nop(100); /* muß sein, sonst keine Enumeration! */
|
42 | return count; |
43 | }
|
Das habe ich bei anderen Implementierungen so noch nicht gesehen. Eine Analyse ergab, dass das auch nicht nötig ist. Die einzige Stelle an der die Verzögerung bei mir nötig war ist in der Funktion:
1 | void DoSetAddress(void) |
2 | {
|
3 | ACK(); // das muß bei diesem Core davor! |
4 | // temp: Nop neu hinzugefügt
|
5 | Nop(1000); |
6 | USB_SetAddress(CMD.SetupPacket.wValue); |
7 | }
|
Die wird im Normalfall nur genau ein mal bei der Enumeration aufgerufen und hier ist die Zeit auch ziemlich unkritisch. Nachdem ich diese beiden Änderungen gemacht habe läuft es komplett rund egal ob ich den STM mit 72MHz oder 48MHz laufen lasse und egal welche Optimierung verwendet wird. Damit habe ich ein wesentlich besseres Gefühl mit dem gesamten USB Code von WS da immer wiederkehrende Delayschleifen komplett entfallen.
Noch ein Nachtrag: Nachdem ich mit Tsvetan von Olimex Kontakt kam jetzt die Bestätigung: "Thanks! We will definitely release STM32F303 version"
temp schrieb: > Die einzige Stelle an der > die Verzögerung bei mir nötig war ist in der Funktion Ich habe deinen Änderungsvorschlag mit einem STM32F103C8 und einem STM32F303CC verifiziert. Funktioniert. Ich freue mich immer, wenn wir uns gegenseitig unterstützen können.
Stefanus F. schrieb: > Ich freue mich immer, wenn wir uns gegenseitig unterstützen können. Freut mich auch. Bei dieser USB-Implementierung war es vor allem deshalb sehr nervig weil die NOP()-Schleifen im Interrupt laufen, also genau da wo sie mit Sicherheit nicht haben will.
moin moin, bin auf Malle, da dauert alles etwas laenger... >>Die Frage ist: Hat schon mal jemand von euch USB und CAN gleichzeitig >>benutzt mit einem Vertreter der STM32F303 Serie? ja, geht. siehe auch: Beitrag "stm32f303cc USB mappen" Bei den Olimex-Boards ist mir zuviel drauf. Benutze daher Black-Pills mit F303CC, die Pins sind so wie bei den Blue-Pills. so, nun wieder in die Sonne. Pieter
Hast du das wirklich einmal probiert? Die Interrups sind ja nur ein Teil des Problems. Der STM32F303CC hat im Gegensatz zum STM32F303RE nur 512byte SDRAM für USB und CAN gemeinsam. Im Manual zum RE steht, dass von den 1024Byte gemeinsamen RAM die obersten 256Byte für CAN drauf gehen wenn enabled. Bleiben also noch 768Byte für USB übrig. Wie das beim 303CC ist steht da nicht. Deshalb würde mich brennend interesieren was in dieser Konstellation passiert. Hast du ein Demo-Projekt dafür?
Soweit ich weiß, kann der STM32F303CC nicht gleichzeitig USB und CAN. Im Referenzhandbuch vom STM32F302CC Kapitel 32.3 "USB implementation" steht ganz am Anfang: "The 512 bytes are totally available to USB; nothing is shared with CAN" Was letztendlich bedeutet, das CAN dann tot ist, weil es kein RAM hat. Im Referenzhandbuch vom STM32F303CC ist der Wortlaut etwas anders: "When the CAN peripheral clock is enabled in the RCC_APB1ENR register, only the first 768 Bytes are available to USB while the last 256 Bytes are used by CAN." Da das CC Modell nur 512 Bytes RAM hat, bleibt für CAN nichts mehr übrig. Meine Meinung dazu ist: ST hätte auch einfach klipp und klar schreiben können: "On devices with 512 Bytes buffer USB and CAN cannot be used together". Aber mir ist schon mehrmals aufgefallen, dass sie eventuell überraschende Einschränkungen gerne verheimlichen. Ich verstehe den Beitrag von Pieter so, dass er gerne die Black-Pill Boards verwendet, ungeachtet der USB+CAN Einschränkung.
Ich gerade in diesem Zusammenhang einen Hammer in dem Errata Dokument entdeckt. ------------------------------------------------------------------ Data Read when the CPU accesses successively SRAM address “A”and SRAM address “A + offset of 16 KBytes (0x4000)” Description: If the CPU writes to an address A in the SRAM memory and immediately (the cycle after) reads an address B in the SRAM memory, while B = A+0x4000, the read operation will return the content at address A instead of the content of address B. Workaround: Revision Z devices: The likelihood of such condition to occur is rare and will happen with a code having more than 16 Kbytes of RAM usage. In case of hand-written assembly code, the work-around is to insert a NOP between consecutive write and read from addresses A and A+0x4000 respectively. With a C compiler, it is advised to limit the SRAM usage to 16 Kb instead of 40 Kb. The 8 Kb of CCM memory can also be used for data to have a 24 Kb total RAM space available. Revision Y devices: fixed ------------------------------------------------------------------ WTF? Ich soll im Ernst auf mehr als 50% vom RAM verzichten, weil er bei Lesezugriffen auf die höheren Adressen sporadisch die falschen Zellen ausliest? Also eigentlich müsste das zu einer Rückrufaktion führen. Was hat es mit dem Y und Z auf sich? Ich hätte jetzt erwartet, dass Revision Z die neuere ist, aber dann kann der Kommentar "fixed" bei Y nicht passen.
So jetzt von mir Hammer Nr. 2: vor mir liegt folgendes Board: https://robotdyn.com/catalog/development-boards/stm-boards-and-shields/stm32f303cct6-256-kb-flash-stm32-arm-cortexr-m4-mini-system-dev-board-3326a9dd-3c19-11e9-910a-901b0ebb3621.html Mit einem stm32f303cc. Da habe ich jetzt die Software installiert die ich im Zusammenhang mit dem xxRE gemacht habe. Ein einfaches USB-CAN-Interface mit SLCAN Protokol. Einzig die Adressierungsart des USB-Speichers (1x16bit, 2x 16bit) habe ich da angepasst. Der darin enthaltene USB-Code (WS) nimmt sich 484Bytes vom USB Ram. Eigentlich sollte das ja nicht gemeinsam mit CAN gehen. Aber oh Wunder, es funktioniert genauso wie mit dem STM32F303RE. Dass muss ich erst mal verdauen. Welchen Speicher benutzt denn dann das CAN-Interface? Eventuell haben beide 1024byte. Der eine in 512/512Byte geteilt und der andere in 768/256Byte mit dem Hintergrund bei den größeren Typen mehr für den USB Teil zu ermöglichen. Auf alle Fälle schaufelt sich der Rechner über das Board und einem USBtin im 1ms Takt bei 125kbaud fröhlich Daten hin und her. Die Frage die sich dabei stellt ist was sich STM dabei denkt.
Stefanus F. schrieb: > Was hat es mit dem Y und Z auf sich? Ich hätte jetzt erwartet, dass > Revision Z die neuere ist, aber dann kann der Kommentar "fixed" bei Y > nicht passen. Ich denke Y ist die neuere. Im Register DBGMCU->IDCODE kannst du das auslesen. Bei mir steht da 0x1003 drin. Das bedeutet 'Y'. Demnach keine Panik! Der letzte Eintrag in der revision history ist von 2016. Ich denke die 'Z' Variante wirst du kaum noch auftreiben könnnen.
Ich hab noch einen zum Thema USB-Code von WS. Die Ursache Delays in den Interruphandler einzubauen hatte folgende Ursache:
1 | volatile uint8_t DeviceAddress=0; |
2 | void DoSetAddress(void) |
3 | {
|
4 | ACK(); // das muß bei diesem Core davor! |
5 | DeviceAddress=CMD.SetupPacket.wValue; |
6 | // Nop(1000);
|
7 | // USB_SetAddress(CMD.SetupPacket.wValue);
|
8 | }
|
Wenn der PC dem Device seine zukünftige Adresse mitteilt, muss das wie oben mit ACK() beantwortet werden. Allerdings darf die während dieses Transfers noch nicht im Register USB_DADDR gesetzt werden. Erst wenn das Packet draussen ist darf die neue Addresse da hinein geschrieben werden. Deshalb merke ich mir die an Stelle nur und setze sie dann erst im Interrupthandler:
1 | ....
|
2 | else /* IN, also Paket wurde gesendet */ |
3 | {
|
4 | if (DeviceAddress) |
5 | {
|
6 | USB_DADDR = 0x80 | DeviceAddress; |
7 | DeviceAddress=0; |
8 | }
|
9 | |
10 | trace("in\n"); |
11 | USB_EpRegs(EpNum) = EpStatus & ~CTR_TX & EP_NoToggleBits; |
12 | if (EpNum == logEpCtrl) |
13 | ....
|
Mit diesen Änderungen funktioniert das ganze ohne einen einzigen NOP() während eines Interrupts.
temp schrieb: > Das liest sich für mich so, dass bei den D/E Typen USB und CAN > gleichzeitig benutzt werden kann Ich habe mir das nochmal in Ruhe angeschaut und die Wortlaute auch mit anderen STM Serien verglichen. Dadurch bin ich zum Schluss gekommen, dass man wohl bei allen STM32F303 Modellen USB und CAN gleichzeitig verwenden kann. Der Unterschied ist: STM32F303xB und xC haben 512 Bytes für USB + 512 Bytes Speicher für CAN. STM32F303xD und xE haben 1024 Bytes für USB und CAN, wovon die letzten 256 byte von CAN belegt werden, wenn man beides nutzt. Die Fußnoten, die im Eröffnungsbeitrag zitiert wurden, beziehen sich nur auf die 1kB Modelle (xD und xE). In der AN4879 auf Seite 4 habe ich klare Aussagen gefunden: https://www.st.com/content/ccc/resource/technical/document/application_note/group0/0b/10/63/76/87/7a/47/4b/DM00296349/files/DM00296349.pdf/jcr:content/translations/en.DM00296349.pdf STM32F102, STM32F103 haben gemeinsam genutzt 512B, also können USB und CAN nicht zugleich benutzt werden. STM32F070x6/B, STM32F072, STM32F078, STM32F04x, STM32F302x6/8, STM32F302xD/E, STM32F303xD/E haben 1KB gemeinsam genutzten Speicher. Davon sind 768 Bytes für USB und 256 Bytes für CAN, wenn man beide Schnittstellen zugleich verwendet. STM32F105/107, STM32F302xB/C, STM32F303xB/C, STM32F373, STM32F4, STM32F7, STM32H7, STM32L0, STM32L1, STM32L2, STM32L3 und STM32L4 haben für USB und CAN unabhängige Speicher.
Stefanus F. schrieb: > In der AN4879 auf Seite 4 habe ich klare Aussagen gefunden: > https://www.st.com/content/ccc/resource/technical/document/application_note/group0/0b/10/63/76/87/7a/47/4b/DM00296349/files/DM00296349.pdf/jcr:content/translations/en.DM00296349.pdf Hallo Stefan, danke für die Info. Ich hab das auch gleich an Olimex weitergegeben. Ziel ist ein einfacher CAN Recorder auf SD-Karte, der gleichzeitig als USB-CAN Interface arbeiten sollte. Das o.g. Olimex-Board ist dafür ideal da komplett alle nötigen Bestandteile drauf sind. Ist für Pedelecs mit BionX Antrieb gedacht zur Fehlersuche und als Interface für die Bikeinfo-Software. Wenn ich das weitergeben will ist natürlich ein fertiges Board ohne die Notwendigkeit einen Lötkolben anfassen zu müssen die beste Variante.
moin, bei unserem Hotel funktioniert Internet nur bei schoenem Wetter...und dann bin ich am Strand. Das Black-Pil hat einen STM32F303CC drauf und stellet bei mir einen USB-HID<->CAN Umsetzer bereit. Die USB-HID Unit ( Pascal ) ist fuer 103C8 und 303CC identisch, beim 303 wird nur zusaetzlich der USB Interrupt umgebogen, zeigt aber auf die selbe ISR wie beim 103. so, nun wieder in die Sonne. Pieter
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.