Hi,
als frischgebackener Besitzer eines STM32F103 Stamp Moduls ich habe das
CAN Loopback Beispiel aus der ST Standard Lib (3.4.0) ausprobiert und
bin dabei auf einen merkwürdigen Effekt gestoßen.
Im Loopback-Modus kann man die CAN-Nachrichten auf dem Tx-Pin mitlesen.
(Der ganze Quellcode ist im Attachment)
Ich habe dafür wie folgt initialisiert:
An Pin 9 (Port B) kann ich dann das Tx-Signal auslesen.
Dann wird das CAN-Polling ausgeführt, danach die Interrupt-basierte
CAN-Übertragung. Im Referenzbeispiel sind die Funktionen bereits
ausformuliert.
Der Erfolg der CAN-Übertragungen soll über zwei LED's, der Mißerfolg
über eine dritte LED angezeigt werden.
Beispiel für die "Erfolg"-LED bei CAN-Loopback:
/* setup Port 7 for Ports A as output with 2MHz clock: */
5
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
6
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
7
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
8
GPIO_Init(GPIOC, &GPIO_InitStructure);
9
10
GPIOC->BSRR = GPIO_Pin_7; /* LED On */
Wo ist nun das Problem:
Beim ersten Start nach dem Flashen klappt die CAN-Übertragung- Moment:
das CAN-Empfang via Interrupt klappt schon nicht mehr, aber immerhin
CAN-Polling.
Damit es am Oszilloskop ordentlich was zu sehen gibt, wird die Funktion
CAN-Interrupt-Testfunktion endlos aufgerufen. Leider wird nichts über
die ISR empfangen (kein Einsprung), aber die Pakete gehen raus (man
sieht es auf dem DSO).
Wenn ich nun auf den Reset-Button gehe und das Programm neue starte,
gibt es keine Pakete mehr zu sehen, ja sogar die Funktion CAN-Polling
geht nicht.
Wenn ich spaßeshalber das Remapping der CAN-Pins weglasse und
neuprogrammiere, zeigt die LED Erfolg für das Polling an. Ein
Wiedereinführen des Remapping zaubert wieder die Pakete auf das DSO -
bis zum nächsten Reset.
Wenn ich den Strom für 30s aus und dann wieder einschalte, geht es immer
noch nicht: Der Tx-Pin zeigt konstant '1' Pegel.
Meine Vermutung: irgendwelche Settings stimmen nach dem Reset nicht und
werden merkwürdigerweise im Programm nicht richtig gesetzt.
Kann mir jemand helfen?
Grüße
schnack
STMF32F103 ist eim Medium-Device. Dein Startup sieht nach einem
XL-Device aus. Könnte sein, dass die Interruptvektoren oder was anderes
im Startup nicht passt.
Was hast Du für eine CAN Infrastruktur dran oder nur den Loopback?
Ansonsten laufen eigentlich bei mir die 2 Beispiele der FW-Lib 3.4.0.
Dort wird aber von weiteren bereits erfolgten Routinen zur
Initialisierung (EVA-Bords) ausgegangen. Kann bei Dir zB. keine
Systeminits, wie Takt, PLL, ABP-Takte usw. finden, oder übersehen?
Nochwas. Bei den 103ern geht USB und CAN nicht gemeinsam. Diese
Erkenntnis hatte ich auch zunächst im Datasheet überlesen.
Hi Matthias,
auf dem Stamp ist ein STM32F103RET6 verbaut mit immerhin 512KB Flash.
Laut Referenz-Manual ein High Density Device:
● High-density devices are STM32F101xx and STM32F103xx microcontrollers
where
the Flash memory density ranges between 256 and 512 Kbytes.
● XL-density devices are STM32F101xx and STM32F103xx microcontrollers
where the Flash memory density ranges between 768 Kbytes and 1 Mbyte.
Damit liege ich mit meiner Definition im Makefile:
1
SYMBOLS = -DSTM32F10X_XL
auf jeden Fall falsch - danke!
Die CAN-Struktur ist bislang nur ein Loopback zum "Mithören". In einem
zweiten Schritt wollte ich es an ein bestehendes Netz anschließen.
Die Takte werden in der system_stm32f10x.c definiert - hier ist z.B. die
SystemInit.
Ich werde gleich mal prüfen, was die Definition als High Density Device
liefert.
Grüße
schnack
>/*!< At this stage the microcontroller clock setting is already> configured, this is done through SystemInit() function which is> called from startup file (startup_stm32f10x_xx.s) before to branch to> application main. To reconfigure the default setting of SystemInit()> function, refer to system_stm32f10x.c file */
Aber wo rufst Du es auf?
Ruf am Anfang mal diese beiden Routinen auf:
Hi,
also:
* die Definition habe ich geändert.
* außerdem hatte ich die startup_stm32f10x_xl.s statt
startup_stm32f10x_hd.s gewählt (darauf hast Du Dich vermutlich
bezogen..)
Beides war falsch und beides habe ich korrigiert. Aber das war es leider
nicht. Weiterhin habe ich diesen "merkwürdigen" Effekt. Ich prüfe jetzt
auch, ob der Code zum Init der eval-Boards noch mehr enthält.
Grüße
schnack
Hi Matthias,
ok- ich bin kein Assembler-Experte. Mein Verständnis ist, daß die
Syteminit() im Reset-Handler aufgerufen wird.
Aus dem Assembler-File startup_stm32f10x_hd.s:
1
.section .text.Reset_Handler
2
.weak Reset_Handler
3
.type Reset_Handler, %function
4
Reset_Handler:
5
6
/* Copy the data segment initializers from flash to SRAM */
7
movs r1, #0
8
b LoopCopyDataInit
9
10
CopyDataInit:
11
ldr r3, =_sidata
12
ldr r3, [r3, r1]
13
str r3, [r0, r1]
14
adds r1, r1, #4
15
16
LoopCopyDataInit:
17
ldr r0, =_sdata
18
ldr r3, =_edata
19
adds r2, r0, r1
20
cmp r2, r3
21
bcc CopyDataInit
22
ldr r2, =_sbss
23
b LoopFillZerobss
24
/* Zero fill the bss segment. */
25
FillZerobss:
26
movs r3, #0
27
str r3, [r2], #4
28
29
LoopFillZerobss:
30
ldr r3, = _ebss
31
cmp r2, r3
32
bcc FillZerobss
33
/* Call the clock system intitialization function.*/
34
bl SystemInit
35
/* Call the application's entry point.*/
36
bl main
37
bx lr
38
.size Reset_Handler, .-Reset_Handler
Am Ende ruft er SystemInit() und dann main() auf. Wenn er das nicht
täte,
dürfte ja doch gar nichts funktionieren- oder?
Grüße
schnack
Hallo,
der Effekt tritt differenzierter auf, als ich bisher bemerkt habe: wenn
ich das Target via JLINK flashe und starte, klappt das CAN-Polling mit
Remap - aber nicht nach einem Reset (wie oben beschrieben)
Wenn ich dagegen mit dem STMFlashLoader via USART flashe, tritt der
Fehler sofort auf.
Offenbar "verbessert" der JLINK die Lage etwas...
C. D. schrieb:> Am Ende ruft er SystemInit() und dann main() auf. Wenn er das nicht> täte,> dürfte ja doch gar nichts funktionieren- oder?
Das macht nur eine Herstellung einer Default-Einstellung. Reicht nicht
aus.
Hi Matthias,
so ganz ist mir das nicht klar: Die SetupSystem() habe ich in den
Sourcen nicht gefunden. Aber ich habe in der system_stm32f10x.c die
Funktion SetSysClockTo72() gefunden. Diese scheint gerade die Settings
Deiner SetupSystem() zu wählen (s.u.). Diese Funktion wird wiederum in
der SystemInit durch
1
(...)
2
/* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
3
/* Configure the Flash Latency cycles and enable prefetch buffer */
4
SetSysClock();
5
(...)
aufgerufen. Ich habe den Eindruck, daß alle Takte laufen - so wie es
sein soll. Da ich ja via JLINK zumindest initial die CAN-Frames sehen
kann, hoffe ich, daß es irgendein Detail ist, was noch fehlt.
1
static void SetSysClockTo72(void)
2
{
3
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
4
5
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
6
/* Enable HSE */
7
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
8
9
/* Wait till HSE is ready and if Time out is reached exit */
Habe ich auch keine wirkliche Idee mehr. Bist Du sicher, dass das
Startup .s zu win-arm passt? In Bsp. sehen die dort anderes aus. Mit
Keil laufen auf jedem Fall die Startups der STM FW-Lib. Mit dem
AtollicTrue Studio gehen die nicht, basiert auch auf Win-Arm.
Hast Du ein Blinky schon mal einwandfrei zum laufen gebracht?
Oder lade Dir mal zum testen die Keil MDK EVA-Version runter.
http://www.keil.com/arm/mdk.asp
Hi Matthias,
danke für Deine Unterstützung!
Ja, die blinkende LED läuft einwandfrei. Inzwischen habe ich den Fehler
einkreisen können. Erstmal habe ich die Takterzeugung für die Periperie
angepaßt und die Frameerzeugung klappt nun stabil (auch nach Reset). Ich
kann jetzt auf beiden CAN-Ports je nach Remap die CAN-Frames (am TX-Pin)
sehen- dafür gibt es folgenden Endlos-Code:
1
TestRx = CAN_Polling();
2
3
/* CAN transmit at 500Kb/s and receive by interrupt in loopback mode */
4
5
while (1) {
6
TestRx = CAN_Interrupt();
7
8
9
if (TestRx == SUCCESS)
10
success2();
11
12
13
miniDelayLoop(); // winziger Delay
14
}
Wobei zu beachten ist, daß das Interrupt-Handling nicht aktiviert ist.
Sobald ich im Code (davor) die Funktion NVIC_Configuration() starte,
gibt es keine Frames mehr. Ich kann nur vermuten, daß ich beim
Konfigurieren des Interrupts den Prozessor einen Fehler mache und beim
Auftreten des Interrupts läuft er in die Pampa. Der Interrupt
USB_LP_CAN1_RX0_IRQn hat aber bei allen Devices (, die CAN unterstützen)
den gleichen Index:
1
USB_LP_CAN1_RX0_IRQn = 20, /*!< USB Device Low Priority or CAN1 RX0 Interrupts */
haben. Hier die fragliche Funktion, die ich (gegenüber der REferenz) um
den das Statement NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); ergänzt
habe.
1
void NVIC_Configuration(void)
2
{
3
NVIC_InitTypeDef NVIC_InitStructure;
4
5
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); // FLASH Vector Table ab 0x08000000 (Default)
Interruptproblem: Kommt immer wieder auf das Startup/Interruptvektoren
zurück.
Stimmt die CAN-Bitrate? Oszi überprüft? Eventuell kann man daraus
Rückschluß ziehen, ob die Systemfrequenz laut SystemInit überhaupt
stimmt.
Ggf. hier mal gegenprüfen.
Beitrag "STM32 CAN Baudrate Berechnung (Can Bit Timing)"
(...) und in der Testfunktion CAN_Interrupt wird der so konfigurierte
Interrupt aktiviert:
1
/* CAN FIFO0 message pending interrupt enable */
2
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
Das Problem tritt aber nur auf, denn NVIC_Configuration() aufgerufen
wurde - die Interrupt-Aktivierung habe ich nicht auskommentiert, ist
also immer aktiv.
[EDIT]
Baudratenberechnung: ich meine, ich habe die Beispielwerte nicht
geändert, werde aber den Link auswerten.
Konfiguriert ist:
1
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
2
CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;
3
CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;
4
CAN_InitStructure.CAN_Prescaler=5;
Nach Deinem Excel-Sheet (super Sache :-) ) läuft dies auf 450kHz hinaus,
bzw. 2.2us. Im Oszi sind es ca. 2,24 us.
[/EDIT]
Grüße
schnack
>CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
Ist korrekt, der Fehler liegt nicht daran.
Die Bitraten in der FW-Lib sind für 8MHz fPCLK (APB1), stimmen also nur
bedingt. Meist wird aber mit APB1 = 36MHz gearbeitet.
C. D. schrieb:> NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); // FLASH Vector Table ab
0x08000000 (Default)
Aha, lass dir mal den Wert von der Vector-Table ohne den Funktionsaufruf
ausgeben.
Hi Matthias,
hier liegt ja vielleicht der Hund begraben:
> Bist Du sicher, dass das Startup .s zu win-arm passt? In Bsp. sehen die> dort anderes aus.
Die Startup-Datei habe aus dem Verzeichnis für ride-gcc entnommen
(attachment).
Bislang hat damit alles - na ja, also die blinkende LED immerhin -
funktioniert. Ich bin jetzt (nach Deinem Hinweis) von der XL auf die HD
Variante umgestiegen.
Grüße
schnack
Hallo,
also der Wert der Vektor-Tabelle habe ich durch hinsteppen ermittelt,
siehe attachment. Nun ist 134217728 = 0x8000000.
Die Statements mit reg sind (völlig überflüssig und) von mir.
Grüße
schnack
Hallo Matthias,
Dein Linker-Skript (auf 512K Flash, 64K RAM modifiziert) hat leider
keine Änderung gebracht.
Ich fasse noch einmal zusammen:
A) Mit Aufruf "NVIC_Configuration()":
* CAN-Frames nach Download via JTAG, keine ISR-Behandlung
* nach Reset keine CAN-Frames, offenbar springt er beim Empfang in eine
ISR und "verendet" dort (These dazu unten)
B) Ohne Aufruf "NVIC_Configuration()":
* CAN-Frames nach Download via JTAG oder USART, keine ISR-Behandlung
* nach Reset das gleiche Verhalten
Und schließlich:
A*) Mit Aufruf "NVIC_Configuration()":
Wenn ich (nicht in Eclipse) direkt im gdb (CodeSourcery) debugge, gibt
er nach monitor reset und continue ebenso keine Frames aus. Bei
Unterbrechen der Ausführung mit Crtl-C meldet er:
1
Program received signal SIGTRAP, Trace/breakpoint trap.
2
0x080030c8 in WWDG_IRQHandler ()
Wieso er in den Windowed Watch Dog Handler läuft, ist mir allerdings
komplett ein Rätsel - schließlich ist dieser Interupt nicht
konfiguriert. Offenbar ist dies der Interrupt-Handler, den er irrtümlich
nach CAN-Frame Empfang aktiviert - und der besteht nur aus einer
Endlosschleife..
Grüße
schnack