Forum: Mikrocontroller und Digitale Elektronik CH32V003 Resetverhalten


von Vanye R. (vanye_rijan)


Lesenswert?

Ich benutze den CH32V003 im SOT8(!) jetzt schon so ein Jahr fuer diverse 
kleine Spielereien. Bisher hat alles im grossen und ganze so 
funktioniert wie ich mir das vorstelle. Aber gelegentlich kam es schon 
mal zu irgendeinem komischen Verhalten und ich hab das Teil dann mit 
minichlink -u wieder auf die Beine geholfen.

Aktuell hab ich gerade eine kleine Anwendung laufen die nichts anders 
macht als mit tim1 300khz erzeugen zu lassen und dies an PC4, PA1 und 
PA2 auszugeben.
Das funktioniert auch! Aber erstaunlich oft haengt sich der Controller 
beim starten weg! Das Programm laeuft dann direkt nach dem flashen wenn 
es vom debugger gestartet wird, aber nur sehr gelegentlich nach einem 
Powercycle in meiner Hardware.

Ich wuerde ja sagen irgendwas stimmt mit meiner Resetbeschaltung nicht, 
aber der SOT8 hat keinen Reseteingang.
Ich hab auch schon minichlink mit -d oder -D probiert ohne das ich da 
eine Besserung sehen wuerde.

Hab ich da was uebersehen?

Vanye

von Cyblord -. (cyblord)


Lesenswert?

Vanye R. schrieb:
> Hab ich da was uebersehen?

Abblockkondensatoren

von Vanye R. (vanye_rijan)


Lesenswert?

Ja, der Gedanke liegt natuerlich nahe. Ich hatte aber schon direkt an 
den Beinen des SOT8 einen 100nF drueber geloetet. Und mehr ist da ja 
nicht....

von Dieter D. (Firma: Hobbytheoretiker) (dieter_1234)


Lesenswert?

Häng mal ein Oszi an den Versorgungsspannungseingang und nimm den 
Verlauf auf.

von Vanye R. (vanye_rijan)


Angehängte Dateien:

Lesenswert?

Ich hab da wohl wirklich einen Bug der Extraklasse in meinem System. :-D

Mein Programm sieht so aus:

int main()
{
  SystemInit48HSI();        //Systemclock auf 48Mhz setzen
  pwm_init();               //PWM Initialisieren fuer 300khz an PA1 und 
PA2
  while(1);
}

Das funktioniert IMMER wenn ich es vom Debugger in den STM32V003 
reinlade. Stoepsel ich den Debugger an und lasse es ueber mein 
Labornetzteil laufen, so funktionier es meistens nicht. Aber so jedes 
30-40x startet es doch und laeuft dann auch!
Wenn es nicht läuft dann kommen komische Impulse aus PA2 raus. (siehe 
Bild)
Kommentiere ich SystemInit48HSI() aendert sich nichts am problematischen 
Startverhalten, aber wenn es geht dann sind natuerlich die Frequenzen 
anders weil der Systemtakt niedriger ist.


Als ich damals meine Umgebung aufgesetzt habe, da habe ich ch32fun 
kopiert und als erstes ein einfaches LED-Blink Programm geschrieben. Das 
zeigt dieses verhalten nicht! Es startet also immer.


Nehme ich das als Basis und änder das auf obiges main ab, so 
funktioniert es auch immer! Der Timer gibt also die gewuenschten Signale 
aus.


Danach hab ich damals etwas am "Design" der Umgebung rumgespielt. Also 
nur die Libaries kopiert die ich brauche, andere Verzeichnisse, Startup 
verschlankt, usw. Dabei muss ich wohl einen Fehler gemacht haben der mir 
nicht aufgefallen ist weil es halt immer problemlos funktioniert wenn es 
ueber den Debugger gestartet wird.
Da muss ich wohl noch mal tief in mich gehen und beide Startupcodes 
genau vergleichen. Vermutlich initialisiert der Debugger irgendetwas das 
ich selber vergessen habe. Aber bizarr das es manchmal halt doch 
funktioniert.

Vanye

von Harald A. (embedded)


Lesenswert?

Weiß nicht, ob es das bei diesem Controller auch gibt, aber die NXP LPC 
Controller können ähnlich herumzicken, wenn man die Brown-Out BOD nicht 
sofort als erstes beim Reset setzt.

von Harald K. (kirnbichler)


Lesenswert?

Harald A. schrieb:
> Weiß nicht, ob es das bei diesem Controller auch gibt

Tut es:
1
1.4.4 Power Supply Monitor
2
3
This product integrates a power-on reset (POR)/power-down reset (PDR) 
4
circuit, which is always in working condition to ensure that the 
5
system is in supply. It works when the power exceeds 2.7V; when VDD 
6
is lower than the set threshold (VPOR/PDR), the device is placed in 
7
the reset state without using an external reset circuit.
8
9
In addition, the system is equipped with a programmable voltage 
10
monitor (PVD), which needs to be turned on by software to compare 
11
the voltage of VDD power supply with the set threshold VPVD.
12
Turn on the corresponding edge interrupt of PVD, and you can 
13
receive interrupt notification when VDD drops to the PVD threshold 
14
or rises to the PVD threshold. Refer to Chapter 4 for the values of 
15
VPOR/PDR and VPVD.

(Seite 5 im Datenblatt CH32V003 V1.7)

: Bearbeitet durch User
von Vanye R. (vanye_rijan)


Lesenswert?

Ich muss den Thread noch mal nach oben holen, weil ich gerade etwas Zeit 
gefunden habe mich damit zu beschaeftigen und etwas Rat gebrauchen 
koennte. :)

Zuerst mal die Probleme hier treten mit verschiedenen Programmen auf. 
Ich denke daher nicht das sie an einem Programmierfehler in einem 
bestimmten Programm liegen. Im folgenden betrachten wir aber nur ein 
Programm!
1
int main()
2
{
3
  SystemInit48HSI();        //Systemclock auf 48Mhz setzen
4
  pwm_init();               //PWM Initialisieren fuer 300khz an PA1 und PA2
5
  uart_write(buffer, 0);    //Bullshit, dazu später mehr!
6
  while(1);
7
}

Hier noch mal mein Hardfault handler
1
void HardFault_Handler(void)
2
{
3
4
  //Port PA2 als Ausgang für LED initialisieren                                                            
5
  RCC->APB2PCENR |= RCC_APB2Periph_GPIOA;
6
  GPIOA->CFGLR &= ~(0xf<<(4*2));
7
  GPIOA->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP)<<(4*2);
8
9
  //LED blinkt so grob 5x pro Sekunde mit LED an PA2.                                                      
10
  volatile int i;
11
 doof:
12
  GPIOA->BSHR = (1<<2);                // PA2 = grüne LED auf High setzen                                  
13
  i=100000; while(i-- > 0);
14
  GPIOA->BSHR = (1<<16) | (1<<(16+2)); //grüne LED auf low=aus setzen                                      
15
  i=100000; while(i-- > 0);
16
  goto doof;
17
18
19
}

Uebersetze ich das und lade das mit dem Debugger in mein Testboard so 
passiert das erwartete. Der in pwm_init() initialisierte Timer gibt mir 
ein PWM/Rechteck an PA1 und PA2 aus. Die CPU selber bleibt in der 
whileschleife stehen. Alles wie erwartet.

Die Zeile:
   uart_write(buffer, 0);
gibt einen Buffer von 0Byte aus. Macht also nix!

Kommentiere ich die aus so wird mein Programm um ein paar hundert Byte 
kleiner weil der Compiler erkennt das diese Funktionen die dahinter 
haengen nicht aufgerufen werden. Eine der nicht genutzten Funktionen 
liegt im Flash-Speicher vor main. Hier mal ein Ausschnitt aus dem 
mapfile mit uart_write
1
 *(.text.*)
2
 .text.uart_getFifoSend
3
                0x00000000000000a0       0x2e /tmp/ccvJfodc.ltrans0.ltrans.o
4
 .text.startup.main
5
                0x00000000000000ce      0x216 /tmp/ccvJfodc.ltrans0.ltrans.o
6
                0x00000000000000ce                main
7
 .text.USART1_IRQHandler
8
                0x00000000000002e4       0x6c /tmp/ccvJfodc.ltrans0.ltrans.o

und hier ohne:
1
 *(.text.*)
2
 .text.startup.main
3
                0x00000000000000a0      0x1b4 /tmp/ccPdPsYu.ltrans0.ltrans.o
4
                0x00000000000000a0                main
5
 .text.USART1_IRQHandler
6
                0x0000000000000254       0x84 /tmp/ccPdPsYu.ltrans0.ltrans.o

Im zweiten Fall bin ich mir ziemlich sicher das mein "main" garnicht 
mehr aufgerufen wird. Der CH32 wirft einen HardFault und ich sehe meine 
LED blinken die ich dort im Handler ansteuere.

Auch wenn ich vor der Uartaufruf einen while(1) einfuege funktioniert 
das Programm nicht mehr. Grund dafuer ist das der Compiler erkennt das 
uart_write nicht aufgerufen wird und alle ungenutzten Funktionen aus dem 
Programm wirft. Spiele ich aber etwas mit den Compileroptionen

  -flto -ffunction-sections -fdata-sections

Llaesst er den Code drin und das Programm laeuft wieder.

Funktion und Nichtfunktion haengt also davon ab an welcher Stelle main 
im Programm steht! Das erstaunt mich!  Dabei wird main aus dem 
startupCode aufgerufen:
1
  //Sprung nach Main                                                                                       
2
  __set_MEPC( (uint32_t)main );
3
  // set mepc to be main as the root app.                                                                  
4
  asm volatile( "mret\n" );

Ich sehe nicht wieso das manchmal gehen soll und wieso manchmal nicht!

Aber es kommt noch besser! All das gesagte gilt immer wenn ich das 
lauffaehige Programm ueber den angeschlossenen Debugger in die MCU 
reinlade.
1
./minichlink -3w ./template.bin flash -b

Dabei ist meine TestPlatine die ganze Zeit am Debuger angeschlossen und 
wird auch von diesem mit Spannung versorgt. Ziehe ich die Platine ab und 
steck sie wieder an, oder versorge sie extern mit Spannung, funktioniert 
das Programm auch nicht mehr richtig. Ich lande dann wieder im 
Hardfaulthandler!

Ein paar brilliante Ideen wie man da weiter kommt? :)

Vanye

von Ont E. (ont_e)


Lesenswert?

Keine Idee, aber super interessanter Krimi...

Im Falle vom UART Code, er ja dann da liegt wo "main nicht tut", wenn du 
mal ein Byte sendest, so dass er da auch "durchlaufen muss", knallt es 
dann auch?

von Klaus R. (klausro)


Lesenswert?

Vanye R. schrieb:
> Ein paar brilliante Ideen wie man da weiter kommt? :)

Knifflig. Einen "frischen" CH32V003 hast du schon probiert? Nicht dass 
das Flash (schon) Macken hat und beim "miteincompilieren" von 
uart_getFifoSend liegt das im fehlerhaften Flash (und wird ja nicht 
benutzt...)

von Vanye R. (vanye_rijan)


Lesenswert?

> Knifflig. Einen "frischen" CH32V003 hast du schon probiert?

Klar. Hab ja genug. Es liegt nicht an einem defekten CH32V003.
Ich hab sogar zwei verschiedene Chargen, einmal in SOT8 und
einmal in SOT16. Beide identisches Verhalten.

Ich hab gerade mal eine Ausgabe des mcause Register programmiert,
dazu schreibe ich gleich noch was im anderen Thread. Ist vielleicht doof 
das ich das getrennt habe, aber ist vielleicht auch von allgemeineren 
Interesse wenn man dieses Register auslesen kann.

Jedenfalls fuehrt das nun dazu das der code mit auskommentierten
usart_write immer noch laeuft. Aber nicht wenn ich das Teil
neu starte. Dann gibt es Hardfault, noch dazu einen sehr merkwuerdigen.

Aber dazu anderer Thread.

Vanye

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.