Forum: Mikrocontroller und Digitale Elektronik Arduino CH32V003


von Christoph M. (mchris)


Angehängte Dateien:

Lesenswert?

Im Moment experimentiere ich mit dem CH32V003 und diesem Framwork:
https://github.com/openwch/arduino_core_ch32?tab=readme-ov-file

und versuche hier mal ein paar Eigenheiten zu dokumentieren.

Hier gibt es eine Anleitung:
https://www.hackster.io/patrick-fitzgerald2/program-ch32v003-risc-v-with-arduino-ide-135f6f

Auf welche Pins wird der serielle Port "gemapped".

von Christoph M. (mchris)


Lesenswert?

Hab's raus gekriegt:
1
/*
2
 * CH32V003F4P6 Serial Send Test
3
 * 
4
 * CH32V003F4P6 TX (output) : PD5
5
 * 
6
 * has to be connected to the Programming Dongle RX
7
 * 
8
 * Framework:
9
 * https://github.com/openwch/arduino_core_ch32
10
 */
11
12
13
void setup() {
14
  Serial.begin(115200);
15
}
16
17
uint8_t Counter = 0;
18
19
void loop() 
20
{
21
  Serial.println(Counter++);
22
  delay(100);
23
}

von Christoph M. (mchris)


Angehängte Dateien:

Lesenswert?

Geschwindigkeit Pin-Toggle mit digitalWrite:
255kHz

von Alexander (alecxs)


Lesenswert?

Und ohne die while Schleife?

von Christoph M. (mchris)


Lesenswert?

>Und ohne die while Schleife?
Ist für die Geschwindigkeit.

von Alexander (alecxs)


Lesenswert?

Ja, mich hätte halt mal der Unterschied interessiert wieviel langsamer 
das ist.

von Peter D. (peda)


Lesenswert?

Alexander schrieb:
> Ja, mich hätte halt mal der Unterschied interessiert wieviel langsamer
> das ist.

Schau doch mal in die Arduino core library.

von Alexander (alecxs)


Lesenswert?

steht da nicht drin ;)

von Peter D. (peda)


Lesenswert?

Alexander schrieb:
> steht da nicht drin ;)

Da müßte aber main drinstehen, was dann loop und noch anderen Schrunz 
aufruft.
Ohne ein main beschwert sich jeder C-Compiler heftig.

von Alexander (alecxs)


Lesenswert?

Christoph M. schrieb:
> Geschwindigkeit Pin-Toggle mit digitalWrite:
> 255kHz

Ich wollte hier nur wissen: 233kHz oder so

von Rainer W. (rawi)


Lesenswert?

Peter D. schrieb:
> Da müßte aber main drinstehen, was dann loop und noch anderen Schrunz
> aufruft.

Tut es. Die Aktionen in der Hauptschleife von main() sind überschaubar 
(loop(), Interrupts) solange auf der seriellen Schnittstelle Ruhe 
herrscht:
1
  for (;;) {
2
    loop();
3
    if (serialEventRun) serialEventRun();
4
  }

Die Interrupts

: Bearbeitet durch User
von Christoph M. (mchris)


Lesenswert?

>Christoph M. schrieb:
>> Geschwindigkeit Pin-Toggle mit digitalWrite:
>> 255kHz
Alexander (alecxs)
18.06.2025 15:46
>Ich wollte hier nur wissen: 233kHz oder so
1
 * Results:
2
 * 
3
 * within while loop  255kHz
4
 * without while loop 213kHz

Es wäre interessant zu sehen, wie schnell es maximal wird, wenn man 
direkt auf den Port schreibt.

: Bearbeitet durch User
von Christoph M. (mchris)


Lesenswert?

Oha, der Speicherverbrauch des Framworks scheint exorbitant:
1
/*
2
 * trigonometrie speed test
3
 */
4
5
void setup()
6
{
7
  Serial.begin(115200);
8
}
9
10
void loop()
11
{
12
  float sum=0;
13
14
  float x,y,z;
15
  
16
  Serial.println("start");
17
  for(uint32_t n=0;n<100000;n++)
18
  {
19
    x=sin(2*PI*n/1000);
20
    x=cos(2*PI*n/1000);
21
    sum+=sqrt(x*x+y*y);    
22
  }
23
  Serial.print("sum: ");
24
  Serial.print(sum);
25
}

/tmp/arduino_build_733415/CH32V003_trigonometrieSpeed.ino.elf section 
`.text' will not fit in region `FLASH'

.arduino15/packages/WCH/tools/riscv-none-embed-gcc/8.2.0/bin/../lib/gcc/ 
riscv-none-embed/8.2.0/../../../../riscv-none-embed/bin/ld:  region 
`FLASH' overflowed by 8680 bytes

von Alexander (alecxs)


Lesenswert?

Interessant, doch ein gewisser Unterschied.

von Christoph M. (mchris)


Lesenswert?

Alexander (alecxs)
18.06.2025 19:16
>Interessant, doch ein gewisser Unterschied.

Beim Arduino-Nano ist der Unterschied relativ gesehen kleiner:
1
/*
2
 * Arduino Nano Results:
3
 * 
4
 * within while loop  149kHz
5
 * without while loop 146kHz
6
 * 
7
 */

von Christoph M. (mchris)


Lesenswert?

Beim Arduino Nano passt der obige "trigonometrie Speedtest" locker:
1
Der Sketch verwendet 2570 Bytes (8%) des Programmspeicherplatzes. Das Maximum sind 30720 Bytes.
2
Globale Variablen verwenden 200 Bytes (9%) des dynamischen Speichers, 1848 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Christoph M. schrieb:
> Oha, der Speicherverbrauch des Framworks scheint exorbitant:

Der Grund dafür:

  Beitrag "Re: CH32V003, float wirklich langsam?"

von Christoph M. (mchris)


Lesenswert?

> Oha, der Speicherverbrauch des Framworks scheint exorbitant:
>>Der Grund dafür:
>>  Beitrag "Re: CH32V003, float wirklich langsam?"

Danke.

Auszug:
1
von Yalu X. (yalu) (Moderator)
2
14.04.2025 12:47
3
  
4
In der Mounriver-Toolchain für die CH32-Controller wird die generische
5
soft-fp der glibc verwendet. Diese ist in C implementiert und in
6
keinster Weise an spezifische CPU-Typen angepasst. Die AVR-FP-Routinen
7
hingegen sind in Assembler speziell für diesen CPU-Typ geschrieben.

Was mich dabei wundert: Die RISC-V Architektur ist ja ziemlich genau 
über die Abkürzungen der Erweiterung der Namensbezeichnung.

Die Bezeichnung von WCH ist RISCV-V2A

https://akizukidenshi.com/goodsaffix/CH32V003.pdf

was aber nicht mit der Namenskonvention der RISC-V Organisation 
übereinstimmt.
Im Datenblatt wird dann auf die Bezeichnung des Cores als RV32EC 
verwiesen .

* E => Embedded, nur 16 Register
* C => 16-bit compressed instructions
https://five-embeddev.com/riscv-user-isa-manual/Priv-v1.12/rv32e.html

Da die RISC-V Architekur ja ein mittlerweile recht verbreiteter Standard 
ist, sollte man erwarten, dass es eine schnelle Assembler-Float-Lib dazu 
gibt.

: Bearbeitet durch User
von Rainer W. (rawi)


Lesenswert?

Christoph M. schrieb:
> CH32V003_Arduino_toggleSpeedTest.png

Christoph M. schrieb:
>>Und ohne die while Schleife?
> Ist für die Geschwindigkeit.

Da es dir anscheinend auf Geschwindigkeit ankommt, ist die relativ 
langsame Funktion digitalWrite() doch eher ungeeignet. Wäre an deren 
Stelle das deutlich schlankere digitalWriteFast() nicht naheliegender?

p.s.
Programmcode als PNG ist schon stark :-(

: Bearbeitet durch User
von Nemopuk (nemopuk)


Lesenswert?

Rainer W. schrieb:
> Programmcode als PNG ist schon stark

Kopierschutz

von Christoph M. (mchris)


Angehängte Dateien:

Lesenswert?

Hier mal der Geschwindigkeitstest mit direktem Beschreiben von PC1.
Die Frequenz liegt bei knapp 6MHz.
Bei 48Mhz wäre das also 48/6/2=4 Zyklen pro Schreiben. Die Frage ist: 
Wieviel davon braucht der Sprung?
1
/*
2
 * CH32V003
3
 * 
4
 * Pin Toogle Speed Test
5
 * Results:
6
 * 
7
 * Toggle Speed: 168ns, ~5.95 MHz
8
 * 
9
 * 2025-06-19 mchris 
10
 * 
11
*/
12
13
14
#define RCC_APB2PCENR   (*(volatile uint32_t*)0x40021018) // APB2 Peripheral Clock Enable Register
15
// Controls the clock to APB2 peripherals.
16
// You must enable the clock for GPIOC (by setting bit 4, IOPCEN) before using any GPIOC functions.
17
18
#define GPIOC_CFGLR     (*(volatile uint32_t*)0x40011000) // GPIOC Port Configuration Low Register
19
// Configures the mode and configuration (input/output, push-pull/open-drain, etc.) for pins PC0-PC7.
20
// Each pin uses 4 bits: [MODE1:0 | CNF1:0]. For PC1, configure bits 7:4.
21
22
#define GPIOC_BSHR      (*(volatile uint32_t*)0x40011010) // GPIOC Bit Set/Reset Register
23
// Allows atomic setting or resetting of GPIOC output pins.
24
// Write '1' to bit n (0-15) to set PCn high; write '1' to bit n+16 (16-31) to set PCn low.
25
// Example: GPIOC_BSHR = (1 << 1);      // Set PC1 high
26
//          GPIOC_BSHR = (1 << (1+16)); // Set PC1 low
27
28
void setup()
29
{
30
  // Enable GPIOC clock
31
  RCC_APB2PCENR |= (1 << 4); // Set bit 4 (IOPCEN) to enable GPIOC peripheral clock
32
33
  // Configure PC1 as push-pull output, 50MHz
34
  GPIOC_CFGLR &= ~(0xF << 4); // Clear configuration bits for PC1 (bits 7:4)
35
  GPIOC_CFGLR |=  (0x3 << 4); // Set MODE1=11 (output 50MHz), CNF1=00 (push-pull)
36
}
37
38
void loop()
39
{
40
  // Blink PC1
41
  while (1) {
42
    GPIOC_BSHR = (1 << 1);      // Set PC1 high
43
    //delay(1000);
44
    GPIOC_BSHR = (1 << (1 + 16)); // Set PC1 low
45
    //delay(1000);
46
  }
47
}

von Christoph M. (mchris)


Lesenswert?

Rainer W. (rawi)
19.06.2025 06:40

>p.s.
>Programmcode als PNG ist schon stark :-(
Im Screenshot geht es darum, den Speicherverbrauch anzuzeigen. Ich 
vertraue darauf, dass du die 2 Zeilen bei Bedarf auch selber eintippen 
kannst.

von Benjamin K. (bentschie)


Lesenswert?

Christoph M. schrieb:
> Wieviel davon braucht der Sprung?

Sieht man doch ganz gut auf dem Oszi. 1 Takt High, 1 Takt Low, 2 Takte 
für den Sprung.

Due könntest auch in der Schleife mehrere High/Low wechsel einbauen und 
dann siehst du auf dem Oszi die einzelnen zeiten etwas besser.

von Ralph S. (jjflash)


Angehängte Dateien:

Lesenswert?

... ich habe zwar einen ganz anderen Ansatz für die 
Verwendungsmöglichkeiten von CH32V003, habe aber in meinen Anleitungen 
zum Schluß auch die Möglichkeit der Programmierung unter Arduino 
behandelt und verwende in dieser Anleitung denselben (offiziellen) Core 
wie du, den ich um meine eigenen Programmiermöglichkeiten (unter Linux) 
erweitert hab.

Was ich beim Schreiben einer Anleitung vermisst habe, war ein typisches 
Pinoutmapping des Chips zur Arduino Programmierung und deshalb habe ich 
dann dieses hier im Anhang erstellt.

:-) vllt. kannst du das für deine Seite zur Programmierung von CH32V003 
unter Arduino gebrauchen.

Gruß,
Ralph

von Christoph M. (mchris)


Lesenswert?

>:-) vllt. kannst du das für deine Seite zur Programmierung von CH32V003
>unter Arduino gebrauchen.

Wow, finde ich extrem gut gemacht. Danke :-)

von Christoph M. (mchris)



Lesenswert?

Benjamin K. (bentschie)
19.06.2025 07:42
>Du könntest auch in der Schleife mehrere High/Low wechsel einbauen und
>dann siehst du auf dem Oszi die einzelnen zeiten etwas besser.

Eine sehr gute Idee :-)
Ich meine 2 Cyclen pro Portschreiben zu sehen.
1
/*
2
   CH32V003
3
4
   Pin Toogle Speed Test
5
   Results:
6
7
   Toggle Speed: 82ns or 12.2MHz for ON/OFF
8
9
   2025-06-19 mchris
10
11
*/
12
13
14
15
#define GPIOC_BSHR      (*(volatile uint32_t*)0x40011010) // GPIOC Bit Set/Reset Register
16
17
void setup()
18
{
19
  pinMode(PC1, OUTPUT);
20
}
21
22
#define LEDON {GPIOC_BSHR = (1 << 1);}
23
#define LEDOFF {GPIOC_BSHR = (1 << (1 + 16));}
24
25
void loop()
26
{
27
  // Blink PC1
28
  while (1) {
29
    LEDON;
30
    LEDOFF;
31
    LEDON;
32
    LEDOFF;
33
  }
34
}

von Alexander (alecxs)


Lesenswert?

Ralph S. schrieb:
> Was ich beim Schreiben einer Anleitung vermisst habe, war ein typisches
> Pinoutmapping des Chips zur Arduino Programmierung und deshalb habe ich
> dann dieses hier im Anhang erstellt.

Gleich in die README.md mit reinpacken und einen Pull request schicken.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Christoph M. schrieb:
> Was mich dabei wundert: Die RISC-V Architektur ist ja ziemlich genau
> über die Abkürzungen der Erweiterung der Namensbezeichnung.
>
> Die Bezeichnung von WCH ist RISCV-V2A
>
> https://akizukidenshi.com/goodsaffix/CH32V003.pdf
>
> was aber nicht mit der Namenskonvention der RISC-V Organisation
> übereinstimmt.
> Im Datenblatt wird dann auf die Bezeichnung des Cores als RV32EC
> verwiesen .

RV32EC ist der Name einer von der Berkeley-Universität bzw. RISC-V
International entwickelten Befehlssatzarchitektur.

QingKe V2A ist der Name eines von Nanjing Qinheng Microelectronics
entwickelten Prozessorkerns, der die RV32EC-Architektur implementiert.

CH32V003 ist der Name eines ebenfalls von Nanjing Qinheng
Microelectronics unter der Marke WinChipHead (WCH) entwickelten
Mikrocontrollers, der auf dem QingKe-V2A-Kern basiert.

von Christoph M. (mchris)


Angehängte Dateien:

Lesenswert?

Gerade ist mir eingefallen, dass der PiPico2 ja auch zwei otpionale 
RISC-V Cöre besitzt. Die beiden RV32IMACZ sollten abwärtskompatibel zum 
RV32EC des QingKe V2A sein.
Man kann den Kern in der IDE auswählen und mein hüpergeniales Programm 
(Screenshot) braucht nur 56256 Bytes.

: Bearbeitet durch User
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.