Forum: Mikrocontroller und Digitale Elektronik STM32F303 CAN und USB gleichzeitig


von temp (Gast)


Lesenswert?

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?

von Stefan F. (Gast)


Lesenswert?

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.

von temp (Gast)


Lesenswert?

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.

von temp (Gast)


Lesenswert?

So, zur Info. Ich habe das Nucleo-STM32F303RE getestet und damit gehen 
USB und CAN gleichzeitg.

von Domenik (Gast)


Lesenswert?

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?

von temp (Gast)


Lesenswert?

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.

von temp (Gast)


Lesenswert?

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.

von temp (Gast)


Lesenswert?

Noch ein Nachtrag:
Nachdem ich mit Tsvetan von Olimex Kontakt kam jetzt die Bestätigung:

"Thanks! We will definitely release STM32F303 version"

von Stefan F. (Gast)


Lesenswert?

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.

von temp (Gast)


Lesenswert?

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.

von Pieter (Gast)


Lesenswert?

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

von temp (Gast)


Lesenswert?

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?

von Stefan F. (Gast)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

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.

von temp (Gast)


Lesenswert?

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.

von temp (Gast)


Lesenswert?

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.

von temp (Gast)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

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.

von temp (Gast)


Lesenswert?

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.

von Pieter (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.