platformio / platform-ststm32

ST STM32: development platform for PlatformIO
https://registry.platformio.org/platforms/platformio/ststm32
Apache License 2.0
407 stars 312 forks source link

Support Arduino OPTA PLC #676

Closed maxgerhardt closed 1 year ago

maxgerhardt commented 1 year ago

Per https://docs.arduino.cc/tutorials/opta/getting-started.

Has a STM32H747XI per https://www.arduino.cc/pro/hardware-arduino-opta and is part of the https://github.com/arduino/ArduinoCore-mbed/tree/master/variants/OPTA core

mindrunner commented 1 year ago

Thanks for opening this issue @maxgerhardt! Is there any chance to get this running in some sort of unsupported mode or do I need to wait until some effort of integration has been made?

maxgerhardt commented 1 year ago

Anyone can fork the platform-ststm32 and add the needed JSON board definition, the ArduinoCore-mbed builder script and the Python code adaptions to call into it. A lot of the needed Python changes can be seen by reading + understanding other platforms that use ArduinoCore mbed, such as platform-raspberrypi (Pico) or platform-nordicnrf52 (Nicola).

I'll make a proposal PR at the end of the day.

maxgerhardt commented 1 year ago

Oh it should actually be much easier than this even. This platform already has support for a Portenta H7, which is also using that core. So it should just need a new board definition and a package update for ArduinoCore-mbed.

mindrunner commented 1 year ago

I have a hackaton happening from tomorrow where I will implement a PoC on the Opta. Would really love to use pio instead of Arduino IDE for that to be honest. Not sure where to start, though to get this going easily. Any help or pointing to the right direction is appreciated :)

I'll make a proposal PR at the end of the day.

That would be awesome!! :)

mindrunner commented 1 year ago

Can I load a custom portenta_h7_m7.json into my pio project w/o forking/compiling the whole platformio repo?

maxgerhardt commented 1 year ago

I made the necessary changes. Just create an arbitrary project (e.g. Portenta + Arduino) then replace the platformio.ini with

[env]
platform = https://github.com/maxgerhardt/platform-ststm32.git#opta
framework = arduino
platform_packages = framework-arduino-mbed@https://github.com/maxgerhardt/ArduinoCore-mbed.git

[env:opta]
board = opta
mindrunner commented 1 year ago

Wow, awesome! It almost works. Seems to compile firmware and stuff. However, when uploading, I get an error:

dfu-util: No DFU capable USB device available
*** [upload] Error 74

Even if I explicitly set the upload port/protocol:

[env]
platform = https://github.com/maxgerhardt/platform-ststm32.git#opta
framework = arduino
platform_packages = framework-arduino-mbed@https://github.com/maxgerhardt/ArduinoCore-mbed.git

[env:opta]
board = opta
upload_port = /dev/ttyACM0
upload_protocol = dfu

dfu-util is installed, permissions should be no issue. Arduino IDE is able to upload sketch

maxgerhardt commented 1 year ago

Can you get me the verbose upload invocation in the Arduino IDE (File->Preferences -> Tick "Verbose Upload"), then upload it again. I need to know how it invokes dfu-util.

And the upload_port directive is effectless when using the DFU upload (which is already the default, so it should be deleted alltogether). It uses USB, not a serial port. Actually it uses it for the 1200bps reset it into bootloader, so that's ok.

mindrunner commented 1 year ago

Actually, I did not use dfu in Arduino IDE, because that does not work either. I switched to stlink:

image

Using stlink in platformio results in the following:

xPack OpenOCD x86_64 Open On-Chip Debugger 0.11.0+dev (2021-10-16-21:15)
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
debug_level: 1

hla_swd
Error: open failed
in procedure 'program'
** OpenOCD init failed **
shutdown command invoked

*** [upload] Error 1
 [FAILED] Took 0.71 seconds 

Testing verbos upload now....

maxgerhardt commented 1 year ago

I think I've seen the init problem somewhere, it's because there's not the right reset method / OpenOCD config file used. Need to look at it later what the Arduino IDE uses.

mindrunner commented 1 year ago

Mhmh, it seems to use dfu in Arduino IDE:

/home/le/.arduino15/packages/arduino/tools/dfu-util/0.10.0-arduino1/dfu-util --device 0x2341:0x0364 -D /tmp/arduino_build_291385/sketch_feb21a.ino.bin -a0 --dfuse-address=0x08040000:leave 
mindrunner commented 1 year ago

Full log:

Sketch uses 125288 bytes (15%) of program storage space. Maximum is 786432 bytes.
Global variables use 59264 bytes (11%) of dynamic memory, leaving 464360 bytes for local variables. Maximum is 523624 bytes.
Forcing reset using 1200bps open/close on port /dev/ttyACM0
PORTS {/dev/ttyACM0, } / {} => {}
PORTS {} / {} => {}
PORTS {} / {} => {}
PORTS {} / {/dev/ttyACM0, } => {/dev/ttyACM0, }
Found upload port: /dev/ttyACM0
/home/le/.arduino15/packages/arduino/tools/dfu-util/0.10.0-arduino1/dfu-util --device 0x2341:0x0364 -D /tmp/arduino_build_291385/sketch_feb21a.ino.bin -a0 --dfuse-address=0x08040000:leave 
dfu-util 0.10-dev
dfu-util: Warning: Invalid DFU suffix signature

dfu-util: A valid DFU suffix will be required in a future dfu-util release
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2021 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

Opening DFU capable USB device...
Device ID 2341:0364
Device DFU version 011a
Claiming USB DFU Interface...
Setting Alternate Interface #0 ...
Determining device status...
DFU state(2) = dfuIDLE, status(0) = No error condition is present
DFU mode device DFU version 011a
Device returned transfer size 4096
DfuSe interface name: "Internal Flash  2MB   "
Downloading element to address = 0x08040000, size = 125296
Erase       [=========================] 100%       125296 bytes
Erase    done.
Download    [=========================] 100%       125296 bytes
Download done.
File downloaded successfully
Transitioning to dfuMANIFEST state
maxgerhardt commented 1 year ago

As a test, can you add

upload_command = /home/le/.arduino15/packages/arduino/tools/dfu-util/0.10.0-arduino1/dfu-util --device 0x2341:0x0364 -D $SOURCE -a0 --dfuse-address=0x08040000:leave

to the platformio.ini to make it use Arduino's uploader?

mindrunner commented 1 year ago

Same issue. I think Arduino IDE is doing the reset before:

Forcing reset using 1200bps open/close on port /dev/ttyACM0

I guess I need to trigger that before uploading

mindrunner commented 1 year ago
upload_command = stty -F /dev/ttyACM0 1200 && sleep 2 && dfu-util --device 0x2341:0x0364 -D $SOURCE -a0 --dfuse-address=0x08040000:leave

Brings the device into upload mode before flashing, but then pio errors out again:

Opening DFU capable USB device...
Device ID 2341:0364
Device DFU version 011a
Claiming USB DFU Interface...
Setting Alternate Interface #0 ...
Determining device status...
DFU state(2) = dfuIDLE, status(0) = No error condition is present
DFU mode device DFU version 011a
Device returned transfer size 4096
dfu-util: Error: File ID 2341:0064 does not match device (2341:0364 or 2341:0364)
*** [upload] Error 64
mindrunner commented 1 year ago

2341:0064 is wrong. I think it use the first item from here: https://github.com/platformio/platform-ststm32/compare/develop...maxgerhardt:platform-ststm32:opta#diff-c38a98302e6706833b082aad1ca94d7b14d26513c6201a9ca0b38e435710fa2cR14

So I need to specify my device id (2341:0364) for the build, huh?

maxgerhardt commented 1 year ago

Can you locally go into ~/.platformio/ststm32@XYZ/boards/opta.json and modify the hwids array to only have one entry, which is the 2341, 0064 entry?

mindrunner commented 1 year ago

I solved it, but slightly different way.

extra_scripts = pre:custom_hwids.py

Import("env")

board_config = env.BoardConfig()
board_config.update("build.hwids", [["0x2341", "0x0364"]])
Download    [======================== ]  97%       106496 bytes
Download    [=========================] 100%       109736 bytes
Download done.
File downloaded successfully
Submitting leave request...
Transitioning to dfuMANIFEST state
 [SUCCESS] Took 4.38 seconds 
maxgerhardt commented 1 year ago

Ah my bad it needs to have the 2341:0364 only then. I'll push an update.

mindrunner commented 1 year ago

There are three different Opta models hitting the market this month, so there might also be differnt ids. I only have the RS485 version here.

maxgerhardt commented 1 year ago

But still, the Arduino IDE only knows "OPTA" as a board selection and it uses that exact VID/PID in the dfu-util invocation.

Can you just quickly check that if you remove your extra_script and only have the 2341:0364 hwid in the opta.json that it also works?

mindrunner commented 1 year ago

Correct Path (at least here): ~/.platformio/platforms/ststm32@XYZ/boards/opta.json

Can you just quickly check that if you remove your extra_script and only have the 2341:0364 hwid in the opta.json that it also works?

Works!!

mindrunner commented 1 year ago

But still, the Arduino IDE only knows "OPTA" as a board selection and it uses that exact VID/PID in the dfu-util invocation.

Makes sense, so probably they all have the same id

maxgerhardt commented 1 year ago

Works!!

Does it still fail when you remove the upload_command line though?

mindrunner commented 1 year ago

Yes, I would need something like pre_upload_command = stty -F /dev/ttyACM0 1200 or reset_method like the Espressif 8266 has.

maxgerhardt commented 1 year ago

Ah, I think it doesn't do the reset because I failed to adapt the line for opta too

https://github.com/platformio/platform-ststm32/blob/50f1d3eaaa2cf159ea0f018bc221fe22d909fc08/builder/main.py#L223-L227

maxgerhardt commented 1 year ago

Can you please rm -rf ~/.platformio/platforms/ststm32@* and rebuild + reupload the project, with the original platformio.ini (no upload_command). I've pushed two commits that hopefully correct uploading.

https://github.com/maxgerhardt/platform-ststm32/commit/811f7925949b9c1baa5cc823c4c409df7b4baaff https://github.com/maxgerhardt/platform-ststm32/commit/0f2e802ee2d9015ba334aa60fb7de44aee9e2c3b

mindrunner commented 1 year ago

Works better!

maxgerhardt commented 1 year ago

Thanks to valeros merging the PR and updating the packages, you should now also just be able to use the bleeding edge of the official platform and no platform_packages mods.

[env:opta]
platform = https://github.com/platformio/platform-ststm32.git
framework = arduino
board = opta
mindrunner commented 1 year ago

Woohoo! Thanks everyone. That was much faster than expected! Awesome!!!!

mindrunner commented 1 year ago

@maxgerhardt I have another issue now. My serial monitor is not working when I compile and upload via platformio. Using exactly the same code with Arduino IDE does not have this issue.

Any ideas?

maxgerhardt commented 1 year ago

Code + platformio.ini?Using the PlatformIO serial monitor?lib_archive=no and monitor_dtr=1 doesn't help?

mindrunner commented 1 year ago

Code:

void setup() {
    Serial.begin(9600);
    while(!Serial) ;
}

void loop() {
    Serial.write("hello\n");
}

ini:

[env]
platform = https://github.com/platformio/platform-ststm32.git
framework = arduino

[env:opta]
board = opta
upload_port = /dev/ttyACM0
upload_protocol = dfu

Trying your suggestions now.

mindrunner commented 1 year ago
monitor_dtr = 1
lib_archive = no

does not work either.

mindrunner commented 1 year ago

Mhm, I think that was my bad. I forgot to include Serial.h, which is not needed on Arduino IDE, but compiles without problems on pio (without enabling serial port then)?

Is that expected behaviour?

valeros commented 1 year ago

@mindrunner Usually, you need to include "Arduino.h" only in case when you don't use .ino source files. So, does it work if you include "Serial.h"?

mindrunner commented 1 year ago

Yes, does work for me. I need several imports, which are not necessary on Arduino IDE. I suppose, would replace them all.

Edit: Indeed it does. Thanks so much!

maxgerhardt commented 1 year ago

Remember, when you write in PlatformIO in a .cpp file, you have to #include <Arduino.h> (or at least the functionality you want). This is not a .ino file. The Arduino IDE does preprocessing on the .ino sketches you write, which is exactly re-adding #include <Arduino.h> and predeclaring function prototypes to make it a valid .cpp file.

Every valid .cpp file is a valid .ino file, but not every .ino file is a valid .cpp file. So if you want to keep 100% source code compatibility between the Arduino IDE and PlatformIO, better write valid .cpp files that can be treated as valid for both file extensions.

All of this is documented in https://docs.platformio.org/en/latest/faq/ino-to-cpp.html.