Closed owennewo closed 3 years ago
When using VSCode to upload the project, debugging should work, too. With the "Run->Start Debugging" it is started. Does it reach main()
? When letting the code run and then pausing it, where does it halt (full stacktrace in the GUI)?
No way! Debugging works, that's beyond my wildest dreams!
It is crashing out in init_led(). It's late here, so I'll take a look in the morning.
I was blind but now I see!
Ta muchly!
Owen
On Fri, 4 Sep 2020, 21:33 Maximilian Gerhardt, notifications@github.com wrote:
When using VSCode to upload the project, debugging should work, too. With the "Run->Start Debugging" it is started. Does it reach main()? When letting the code run and then pausing it, where does it halt (full stacktrace in the GUI)?
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/maxgerhardt/pio-gd32f130c6/issues/1#issuecomment-687368787, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADXM462U5G6JXYX3K6DYK73SEFFLJANCNFSM4QZKEJRA .
Ok - I'm still using your project. Break points work in main but I get halted error when calling gpio_mode_set on led or usart pins
One thing I've noticed is that your project is for gd32f130
and my chup is a gd32f103
(ret6 ce6L048 AM1618). I'd also prefer to use arduino rather than spl.
The last line in each of the following causes the halt:
void init_led() {
/* enable the led clock */
rcu_periph_clock_enable(LED1_GPIO_CLK);
/* configure led GPIO port */
gpio_mode_set(LED1_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED1_PIN);
and
void init_uart() {
rcu_periph_clock_enable( EVAL_COM_GPIO_CLK);
/* enable USART clock */
rcu_periph_clock_enable(EVAL_COM1_CLK);
/* connect port to USARTx_Tx */
gpio_af_set(EVAL_COM_GPIO_PORT, EVAL_COM_AF, EVAL_COM1_TX_PIN);
Due to difference between 103 vs 130?
Okay yes a GD32F130 vs GD32F103 is criticial, those can have entirely different memory maps. Writing to the MCU-specific peripherals like GPIO and UART, when using the wrong addresses, will insta-crash it. I'll have a quick look whether the existing framework code here already supports it and we just a need a new .json board definition or if there's more to it.
Wow, your quick!
I've also got another project which looks like this (I think I can remove most of the usb config)
[env:genericSTM32F103CB]
platform = ststm32
board = genericSTM32F103CB
upload_protocol = stlink
debug_tool = stlink
framework = arduino
; monitor_speed = 115200
; board_build.core = maple
build_flags =
-D USBD_USE_CDC
-D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC
-D PIO_FRAMEWORK_ARDUINO_USB_FULLMODE
-D USBCON
-D USBD_VID=0x0483
-D USBD_PID=0x3748
; -D USB_MANUFACTURER="STMicroelectronics"
; -D USB_PRODUCT="STM32 STLink"
-D HAL_PCD_MODULE_ENABLED
-D ENABLE_USB_SERIAL
-Isrc --specs=nano.specs
lib_deps =
; EasyBuzzer
It can sort of enter debug mode, but pauses on the while here:
WEAK void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInit;
/* Initializes the CPU, AHB and APB busses clocks */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
while (1);
}
BTW to unlock this board I ran the following in turn - I think the first and second failed and the 3rd succeeded.
openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c init -c "reset halt" -c "stm32f1x unlock 0"
openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c init -c "reset halt" -c "mww 0x40022004 0x45670123" -c "mww 0x40022004 0xCDEF89AB" -c "mww 0x40022008 0x45670123" -c "mww 0x40022008 0xCDEF89AB" -c "mww 0x40022010 0x220" -c "mww 0x40022010 0x260" -c "sleep 100" -c "mww 0x40022010 0x230" -c "mwh 0x1ffff800 0x5AA5" -c "sleep 1000" -c "mww 0x40022010 0x2220" -c "sleep 100" -c "mdw 0x40022010" -c "mdw 0x4002201c" -c "mdw 0x1ffff800" -c targets -c "halt" -c "stm32f1x unlock 0"
openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c init -c "reset halt" -c "mww 0x40022004 0x45670123" -c "mww 0x40022004 0xCDEF89AB" -c "mww 0x40022008 0x45670123" -c "mww 0x40022008 0xCDEF89AB" -c targets -c "halt" -c "stm32f1x unlock 0"
I was following this: https://github.com/NiklasFauth/hoverboard-firmware-hack As you can tell, a little out of my depth! I'm hoping to repurpose the controller and motors for robotics projects using simplefoc library
Okay after reading up a bit on https://www.cnx-software.com/2015/12/21/gigadevice-gd32-is-a-faster-software-and-pin-to-pin-stm32-compatible-cortex-m3-mcu/ and http://stm32duinoforum.com/forum/viewtopic_f_47_t_2394.html one can conclude that it is software-compatible to the STM32F103C but can have a higher clock speed and more flash.
This means you should be able to actually use the STM32 framework with the genericSTM32F103CB
target as you have done.
However, as you can see above, the clock init code assumes an external 8MHz crystal oscillator on its OSC_IN and OSC_OUT pins (HSE = high-speed-external, then a phase-locked-loop with multiplier 9 to get it its rated 72MHz speed).
Do you see such a quartz crystal on your board? If not, the code has to be slightly altered to run from HSI (internal RC oscillator) plus PLL with different params. The picture of the board doesn't show the area around the chip too well for me to see whether it's there. Not having a crystal will result in HAL_RCC_OscConfig
failing hard.
There doesn't seem to be one. I think I've read somewhere that these gd32 say 72mhz but can only actually do 48hz and that they say m3 but are m0.
According to https://www.gigadevice.com/products/microcontrollers/gd32/arm-cortex-m3/mainstream-line/gd32f103-series/ it can do 108MHz, which is faster than the 72MHz of the STM32F103.
The picture is very clear, thanks. There is no crystal present. Since SystemClock_Config()
is WEAK
one can reimplement it in the user main.cpp
and a small addition to the platformio.ini
is needed. Let me write soome code quickly for HSI init.
Also as a side node, on STM32 chips you need a HSE crystal because only through it you can achieve the needed accurate 48MHz USB clock; can't run on the HSI (high speed internal). That may be different for the GD32 series, but for now, it should be expected for USB to not work. Or does this board have a USB connection to the MCU, which strongly suggests that it's possible with the board?
There is no USB. So what do I need to do to implement in main? I've only coded the other side of the hardware abstraction layer.
Try with the most minimal platformio.ini
[env:genericSTM32F103CB]
platform = ststm32
board = genericSTM32F103CB
upload_protocol = stlink
debug_tool = stlink
framework = arduino
lib_archive = no
and a main.cpp
of
extern "C" void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInit;
/* Initializes the CPU, AHB and APB busses clocks */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSEState = RCC_HSE_OFF;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
while (1);
}
/* Initializes the CPU, AHB and APB busses clocks */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) {
while (1);
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_USB;
PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
while (1);
}
}
void setup() {
pinMode(PC13, OUTPUT);
}
void loop() {
digitalWrite(PC13, LOW);
delay(1000);
digitalWrite(PC13, HIGH);
delay(1000);
}
Does the debugging now reach the new clock init code? (If not, just temporarily replace the existing code). Does it go beyond the clock init?
Yep that works! It skips past while loops ! Thankyou. I'll see if I can get usart working with something like this:
#define RXD2 PA3
#define TXD2 PA2
HardwareSerial serialLeft(RXD2, TXD2);
void setup() {
serialLeft.begin(9600,SERIAL_8N1);
}
void loop() {
while (serialLeft.available()) {
serialLeft.print(char(serialLeft.read()));
}
Cool! Just some notes while I was looking at things:
board = genericSTM32F103RC
not the genericSTM32F103CB
, that should be corrected. for the STM32F103
Notice how the STM32 PLL multipliers only go up to 16. The GD32 goes up to 32. When selecting HSI (or rather "IRC8M" in GD32 speak), the multiplier should be 27 (or RCU_PLL_MUL27
as they call it in the GD32F103 SPL) to get a CK_SYS of 8 / 2 * 27 = 108 MHz
clock, which is the intended target speed of the MCU. So the Arduino-STM32 core cannot unlock the full potential of the chip with only x16 leading to 64MHz.
Just as a sidegig I'm adding GD32F103 SPL support now.
Also the "USB clock must come from external crystal" limitation still holds up in the GD32F103 datasheet.
Partial success. TX (from board to PC) works but is losing 5% of characters. But RX doesn't work. Change the code slightly to send "loop" unsolicited.
void loop() {
delay(500);
serialLeft.print("loop\n");
while (serialLeft.available()) {
serialLeft.print(char(serialLeft.read()));
}
}
As you can see one of the loop
is missing a p!
I've just updated to genericSTM32F103RC
seems to have fixed my missing Tx chars (is that possible) but RX is stil AWOL. Do you think I might need to add a 10k pull up or something? I presume a pullup would be to 5v? I've not used usart before!
I'll be reading the links and docs you've written. Some of it over my head. I've seen those clock tree diagrams before but not understood them. should tx also have pullup?
Partial success. TX (from board to PC) works but is losing 5% of characters. But RX doesn't work.
Loosing outgoing chars or wrongly decoding incoming chars is usually an indication that the UART peripheral of the chip is generating some weird / wrong clock values. There's a percentage threshhold of how wrong the UART clock can be so that it cannot be decoded by the adapter anymore.
Oh of course.. maybe the arduino core still computes UART baud rates based on a wrong 72MHz instead of 64MHz clock. That would explain. Let me quickly search up on how to change the HSI define value that's being used here.
I think the 'loop' TX is fixed already. No dropped characters since changing board name.
Do you think I might need to add a 10k pull up or something?
UART signals idle at the HIGH level (MCU's I/O voltage, which is 3.3V. Though STM32 chips have 5V tolerant pins, I don't know about GD32, so you should rather pullup to 3V3 if at all). However the UART adapter or the MCU should already pull that up weakly. Are you sure the TX signal of the adapter goes straight through to the MCU's receive pin, and there's no other circuitry in the way?
I think the 'loop' TX is fixed already. No dropped characters since changing board name.
Okay then there might have also been some other cause of that, but okay.
PA2 and PA3 are definitely valid on the GD32F103 as UART1 TX/RX pins.
The HardwareSerial
code should also initialize the alternate pin mode correctly.. hm.
I've never used a ftdi before
I only need 3 wires? Rx/tx/gnd with rx/tx swapped between mcu and pc?
Update: just noticed my ground was plugged into dtr. I've moved it over but it hasn't helped.
I only need 3 wires? Rx/tx/gnd with rx/tx swapped between mcu and pc?#
Correct, common GND between PC and MCU (GND <--> GND), RX of the adapter goes to the TX of the MCU, and vice versa. Also the I/O level of the FTDI adapter (the small jumper bridge below the pin header) should be set to 3V)
You can shortly cross reference if that also doesn't work with the SPL example when I'm done.
Jumper and pins moved. My TX missing characters is back. I think you were right earlier. Also no improvement on Rx.
Happy to test spl.
The plot thickens. moserial
still doesn't work for Rx but a cli tool called tio
.
void loop() {
delay(500);
serialLeft.print("loop\n");
while (serialLeft.available()) {
serialLeft.print("before\n");
serialLeft.print(char(serialLeft.read()));
serialLeft.print("after\n");
}
}
I typed 'a' 's' and 'd' and got:
So it's probably a clock thing?
Hm let's check with the SPL code now. I've uploaded the project at https://github.com/maxgerhardt/pio-gd32f103 and it contains a flash-led, print to UART and read from UART code, with the limitation that the RX buffer is probably only 1 byte by the hardware. Can that thing do a LED-blinky or do you see something on the UART (115200 baud)?
Also the line endings are weird, you probably need to edit something for tio
to recognize \n
(LF) as lineending or use \r\n
(CR+LF) in the code for it. However, my favorite serial program is miniterm.py
.
miniterm.py /dev/ttyUSB0 9600
for invocation (sudo apt install python-serial
for installation).
A few errors:
There are no LEDs on board. It's usually enclosed in a plastic hoverboard case. Some of the daughter boards with the IMU chips have LEDs but they are not connected.
Okay I'll double check on linux to fix it. But isn't "LED" at resistor R20 connected to the MCU?
Your eyesight is so much better than mine!
We have Mr Blinky on PB2!
I have identified the problem (wrong filename and filename case sensitivity on linux) and fixed it. Please rm -rf ~/.platformio/packages/framework-spl@*
(otherwise it won't re-download the new version), git pull the latest version of pio-gd32f103 and retry :)
Also adapted the pin for the LED.
Compiles, uploads and blinks but nothing over uart.
Progress! Thanks Max
Oops I'm on 9600 baud PC side. Lets try again
Better. I wonder why it's drifting over to the right? My GUI serial terminal (moserial) is still only showing RX and not sending properly
The content looks very correct.
The output on tio
is mangled because it doesn't interprete the \n
correctly.
Use tio -m ONLCR -b 115200 /dev/ttyUSB0
as explained https://github.com/tio/tio/issues/62#issuecomment-342001367. Or change the code to do \r\n
instead of \n
in the main.c
code.
My GUI serial terminal (moserial) is still only showing RX and not sending properly
Try setting the "CR+LF End" to "None" if possible in the GUI. If it sends these newlines at the end, it may overwrite the hardware buffer with a newline, and as a result may just print a newline.
Or there are more settings involved like maybe it things flow control (DTR+CTS) is on.
I swapped a setting in moserial from 'hardware handshake' to 'software handshake' and its a bit better.
I sent hello - it echoed only first character. I think you said that might be expected;
I swapped a setting in moserial from 'hardware handshake' to 'software handshake' and its a bit better.
Should be set to None if possible, since neither Xon/Xoff or DTR/CTS is used in the hardware or software.
I sent hello - it echoed only first character. I think you said that might be expected;
Yes that should be correct -- to 100% verify it, as I said "CR+LF end" to none and only send 1 char.
So now you can actually fully program the chip using its SPL framework at the intended 108MHz from internal oscillator.
I've had another look at the STM32Duino code and it does seem to get the current clock speed in a generic way that is always correct. So it should know it's running at only 64MHz.
Maybe with fixed terminal settings it'll work flawlessly now?
No joy with ONLCR
flag but \r\n
works. Thanks.
I've switched back to my arduino project. The uart is still twitchy. Your SPL seems flawless.
Hm after reading https://www.st.com/resource/en/reference_manual/cd00171190-stm32f101xx-stm32f102xx-stm32f103xx-stm32f105xx-and-stm32f107xx-advanced-armbased-32bit-mcus-stmicroelectronics.pdf there's a table on page 799 for the UART clock generator and the error values. With the clock tree setup there's maybe not so nice value for PCLK1 after the PLL. Let's try running the core at only 36MHz.
Can you use the new init code
extern "C" void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInit;
/* Initializes the CPU, AHB and APB busses clocks */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSEState = RCC_HSE_OFF;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
while (1);
}
/* Initializes the CPU, AHB and APB busses clocks */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) {
while (1);
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_USB;
PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
while (1);
}
}
And see if that changes something?
Oh and an important aspect may be that usage of the HardwareSerial
stuff doesn't flush at the end and may overwrite the intermediate buffer? Please call .flush()
every time after print()
to be sure. That may be the actual solution.
serialLeft.print("loop\r\n");
serialLeft.flush();
while (serialLeft.available()) {
serialLeft.print("before\r\n");
serialLeft.flush();
serialLeft.print(char(serialLeft.read()));
serialLeft.flush();
serialLeft.print("after\r\n");
serialLeft.flush();
}
I was about to say It's working fine now with no change. WIthout your above changes. So its temperamental. Perhaps the cable was two close to the 32v input I'm feeding it or the pullup isn't quite enough. I'll try your change(s) though. (but it's working at the moment).
So hey Max. I think we are done! I really appreciate your help. There is no way I'd have got this working without you.
I'm hanging out at https://community.simplefoc.com/ - a nice hobbyist community - we are mostly getting mcu working with brushless dc motors and are using a fair bit of STM and Espressif chips to do this.
If you need me to test any more on the SPL version let me know - but I'll be sticking with arduino + genericSTM32F103RC!
Indeed seems to working at some base level now. Though remaining issues are still that the STM32Duino core doesn't understand the GD32F103 chip natively with its 108MHz max speed; the first HSI init code sets it up for only 64MHz. Also the option to switch between HSI and HSE with some given parameters for PLL and clock speed would be nice in the core natively, without having to redirect the clock init function ourselves. Maybe an issue at https://github.com/stm32duino/Arduino_Core_STM32 can be opened for better GD32 series support.
I found a good blog and repo at https://smdprutser.nl/blog/stm32f103-vs-gd32f103/ and https://github.com/smdprutser/GD32Challenge/blob/master/source/gd32.c for GD32 specific extensions to libopencm3 (another bare-metal like framework) that can also use 108MHz speed, quite interesting.
Also closing this issue here since this repo is about the GD32F130 series vs the used GD32F103 series and the chip now runs on two different frameworks succesfully.
Hello @owennewo,
I just saw this thread because I am following @maxgerhardt . Max created this repo when I was developing the hack for the hoverboard sideboards. https://github.com/EmanuelFeru/hoverboard-sideboard-hack-GD
Still works very nice. Thanks again Max!
Regarding the GD32F103RCT6, it should be compatible with the STM32F103RCT6. I didn't try myself but a lot of people confirmed that it works without any change.
Here is my firmware for the mainboard (can be flashed in several ways including platformio): https://github.com/EmanuelFeru/hoverboard-firmware-hack-FOC
Ah, I didn't know the mainboard could also have a GD32F103RCT6 and you have a repo for it :). So the when treating the GD32F103RCT6 like a STM32F103RCT6 it can be programmed with the stm32cube
framework as well like in your repo, and probably all the other frameworks too (if the board variant doesn't expect an external crystal, ahem ArduinoSTM32).
Still funny that the clone actually has the potential to run faster than the original.. Maybe that has some advantages for higher possible PWM frequencies and motor control? :)
Yes, that is indeed funny :relaxed: . Some people reported that the same code executes faster on the GD32 than STM32. So the clone is indeed faster than the original.
@EmanuelFeru - Just had a quick scan of your repo it seems right up my street! Lots for me to learn there. I want to stay on arduino framework and currently working on hobbyist MIT license code but really respect what you have done. Once I get basic closed loop with hall working I'd like to look further at current sensing - I can see you've done a fair bit in that area. Field weakening too. I could ask you a 1000 questions! Your git repo is on my 'read list'.
From the picture you can see a hoverboard controller which has a gd32f103. I have a stlink and can upload sketches. But this board has no led and my attempts to uart using pa2 and pa3 using usb/ftdi yield no data. Maybe the board is rebooting or I'm doing something stupid.
I flashed the code in this project and was hoping to see "Test string for Uart! Blink blinky". But i see nothing in my 'moserial' terminal.
Any thoughts? I just want to see some debug text!