Klipper3d / klipper

Klipper is a 3d-printer firmware
GNU General Public License v3.0
9.42k stars 5.3k forks source link

Port to STM32F1xx #137

Closed archi closed 6 years ago

archi commented 6 years ago

I'm interested in porting klipper to the STM32F1xx, more specifically the 2$ STM32F103C6T8 "blue pill" board. I started with some light poking at the code on my fork, but I used the libmaple variant of the stm32duino project. Since I'm new to the STM32F1xx platform I don't know if that's the best lib to use (and Kevin proposed mBed as an alternative), but at first look it seemed to do all we need. Though I suppose circumventing the Arduino-style digitalWrite/digitalRead might be worthwhile for better performance.

Kevin told me on IRC that @cruwaller might have done some porting, too. So maybe we can coordinate?

Disclaimer & my personal agenda: I have neither a printer nor driver ICs until about mid-April. I plan to design a STM32F103C6T8 carrier board with some I/O expansion (think RAMPS, with a TI PCA9555DWR [I2C 16 bit port expander] for the "slow" non-stepper stuff, e.g. SPI chip select and end stops). But that's a very tentative consideration right now, since I want to get the printer running on stable hardware (RAMPS) before doing any experiments (would be my third custom board layout) and as a employed software dev/masters student I only have so much free time to do this kind of thing.

mmone commented 6 years ago

Did you have a look at http://libopencm3.org/? It supports a wide range of Cortex M MCUs. The STM32 support is supposed to be complete: https://github.com/libopencm3/libopencm3/wiki/Status The project started because the devs wanted a completely OS alternative to the official libs which have difficult licence conditions for OS projects. In this episode of The Amp Hour @1bitsquared (Piotr Esden-Tempski) talks about it starting min. 33:00

archi commented 6 years ago

great, thanks, I will take a look :)

mmone commented 6 years ago

One more tip :-) If you are looking for a STM32 based CNC development platform have a look at: http://www.st.com/en/evaluation-tools/steval-3dp001v1.html it's a reference design by ST. Completely documented with schematics and all.

hg42 commented 6 years ago

the ultimate solution would be a port to something like nuttx, lot's of targets...and seems to have everything we need

theopensourcerer commented 6 years ago

@mmone That is a very interesting looking board.

archi commented 6 years ago

@mmone the point of the stm32 solution [to me] was to do something with my cheap stm32 board, and not buying board that's 50x as expensive ;-) But yes, it surely looks nice.

After spending a while working against libmaple - my blink test flashes, but doesn't seem to be executed, and USB serial (via cdc acm) seems not to work without major patching - and being frustrated how the stm32duino folks adapted that lib - my blink test works, USB works, everything is easy, but it's only really usable from the Arduino IDE; which is nice for some people, but not for this scenario - I give up on that approach.

Long story short: I believe libopencm3 is a good way to do this.

Concerning nuttx: Hm, would definitely hit a lot of targets, but I just don't feel like [personally] spending a lot of time programming a RTOS when a library is enough.

mmone commented 6 years ago

@archi I understood that you where going for something cheap. Just wanted to mention the ST board as it is not well known and for development its sometimes nice to have something capable to start with that has already all the necessary peripherals. As far as STM32 CNC hardware goes this board is the best documented I know. I'm just not sure if the ST stepper drivers are any good though.

As for libopencm3 I have not personally used it for anything yet. But the people behind it guarantee a certain quality I think. The strong connection to the openOCD debugger is also a plus.

wizhippo commented 6 years ago

You could just use st cmsis and hal. Their current license is now BSD style. Another great option would be the ChibiOS HAL(Supports AVR,STM32,LPC214X) as it is Apache licensed.

hg42 commented 6 years ago

@archi nuttx may also be an RTOS, but I think it is very scalable. So you could only use what you need. At the base are a lot of drivers. As far as I see most interesting drivers re already supported.

There are other projects that use them, e.g. smoothieboard-v2 moved with a full-blown firmware to nuttx. PX4 a drone OS seem to move to nuttx, too. This might have some reasons...

Most attractive is that one port would be for all MCUs. Also nuttx has good infrastructure. Klipper is at it's beginning and at this point doesn't really distinguish between boards and cpus and such. I see that each extension (see TMC2130 from cruwaller) needs several changes in base files. I guess all this would be much easier when using a system that already has such structures.

Reinventing the wheel doesn't make much sense.

archi commented 6 years ago

@hg42 I believe this kind of infrastructure change should be best initiated by @KevinOConnor ;) But I don't want to object you, I even believe this would be a good move (support "a lot" via nuttx, and in case something is not supported by nuttx or too slow, just port the current "minimal functionality MCU" to the new target - I mean, it's not a lot of work, if there is a sane lib for the target).

And yeah, even with some fairly limited work I hit some problems with the current MCU source breakdown. Optimally the MCU code would be a "HAL" for the python driver (+ precise scheduler for stepper movement).

@mmone :)

@wizhippo Oh, I didn't know that. Seems I only found outdated information regarding CMSIS. Can you post a link? The ChibiOS HAL also sounds good (only glanced on their website).

hg42 commented 6 years ago

I don't know if nuttx is the ideal candidate, but it seems to be most complete (looking at targets). It seems to be a one man project, but I am surprised how much code is already there.

ChibiOS seems to be another promising project and there are a few more.

Now, I wonder why the smoothie project or PX4 chose nuttx. They will have good reasons because they had no real need for such a change.

I am currently doing some tests on nuttx, but it's still in an infancy stage. I first need to understand the concepts.

wizhippo commented 6 years ago

@archi Couldn't find a good example on github so I posted a copy from the source at https://gist.github.com/wizhippo/92ba6ea5c76367cdde3133d078d3c98d This is form STM32Cube_FW_F3_V1.9.0 applies to the HAL and CMSIS. The simplified middleware for USB is another license though by the looks of it http://www.st.com/software_license_agreement_liberty_v2 though. Actually looking at the link it looks very BSD'ish too.

Kenzu commented 6 years ago

Maybe simba Can be used AS rtos/hal http://simba-os.readthedocs.io/en/latest/boards.html

hg42 commented 6 years ago

you could also look at Marlin2 which has a HAL for STM32F1. Note that 32bit HALs are in different states. The state of those is in the top of https://github.com/MarlinFirmware/Marlin/issues/7076

hg42 commented 6 years ago

simba is missing STM32F1? also LPC176x (Smoothieboard, MKS SBASE, AZSMZ, RE-ARM, etc.)

Kenzu commented 6 years ago

Simba has stm32f1 but not lpc https://github.com/eerimoq/simba/tree/master/src/mcus

hg42 commented 6 years ago

ok, seems the doc linked above is not up to date

Kenzu commented 6 years ago

In the linked docs, it list boards with different mcu. The STM32VLDISCOVERY is an STM32F1 platform. :-)

hg42 commented 6 years ago

STM32VLDISCOVERY... LOL, ok, thanks for destroying my ignorance :-)

dwillmore commented 6 years ago

To be clear, you want to use the USB port of thet STM32F1xx chip to be a serial port and then use the rest of the hardware to perform 3D printer control? The first thing I think you'd need to do is to make sure that the USB can do that without impacting the processor too badly. I.E. what kind of latency do the USB IRQs have on the main loop.

How do the other platforms do it? I guess the Due and the LPC are the ones to look at. I'd be interested in helping you look into this.

dwillmore commented 6 years ago

How do the other native USB speaking boards to this? Use IRQs for the timers and busy wait in the main loop to process USB packets?

julianobst commented 6 years ago

Due uses the USB periperhal of the ATSAM4E8E controller, no external USB to UART IC. The STM32F1xx also contains a USB peripheral module which does propably the most of the USB communication stuff.

archi commented 6 years ago

@dwillmore Sorry for the late reply, but julian is right: The STM32F1xx has built-in USB and doesn't need an external IC. To get the USB acting like a USB serial device the software endpoints need to be defined and registered. I didn't get around to testing cruwallers port, but the file names suggest he wants to offer both UART and USB (see https://github.com/cruwaller/klipper/tree/stm32f1xx/src/stm32f1xx). The code in serial_*.c is missing/just place holders, though.

TBH I understand your concern, but I think/hope it's a negligible issue - as it seems to be with USART interrupts on the AVR: avr/serial.c just puts received data into a buffer. For due (and in my port), there is an additional call to sched_wake_tasks, but if the official due port doesn't have trouble with USB interrupts, I suppose the STM32F1 won't have problems, too.

I am busy with other things right now (real life stuff, and trying to getting my delta printing accurately instead of hammering the nozzle into the print at certain distances [with a fixed XY: low Z is great, high Z is nearly fine, medium Z is up to 0.2mm to low -- but that's OT]), but of course any help is welcome. If you want to take a look at some code, follow the above link to cruwallers port. I mean, if you have time and some experience you can probably fix it up without me :)

hg42 commented 6 years ago

on lpc176x cruwaller uses the serial port to allow debugging output. I guess it's the same for STM32.

Serial and USB-Serial is used quite different.

The main "console" (which isn't used as a console for text commands) seems to use two buffers and I think the input buffer is magically filled by an external USB-library. Commands are "popped" out of this buffer. I am not sure about how the buffer is handled exactly.

On the other hand the debug output console works character based (and I think input is not used).

I already extracted higher console functions (console*) into it's own file and I think this could be made common to all MCU implementations. The only connection between console* and MCU specific code seems to be enabling the tx interrupt which could easily work by exporting it as a standard function name in the MCU specific code.

archi commented 6 years ago

I think you're right: serial_usb.c looks a lot like the normal serial communication, and serial_uart.c offers printf-like functionality. For stm32f1 the init code is not implemented, yet, so I am not sure how it should work there in detail. https://github.com/cruwaller/klipper/blob/stm32f1xx/src/stm32f1xx/usbd_cdc_interface.c#L170 seems to register some buffers with the underlying stuff, so I'd guess these are the magic TX/RX buffers. Mind they are not used anywhere else - but since the code is not finished, yet, I just guess they need to be used in the serial_usb.c for sending/receiving data by the klipper task console_task.

But I am afraid this still needs more work in usbd_cdc_interface.c, as there are a bunch of "/ Add your code here /"...

dwillmore commented 6 years ago

Looks like the STM32F103 had four general purpose timers which should be good for generating the step pulses.

The timers can trigger DMA transfers, so it might be practical to have them do their own setup. In other words, the main loop would fill a buffer with periods and the timer would read them out and perform them.

rossiniscarface commented 6 years ago

The stm32f are very popular for quadcopters. The firmwares are highly optimized. maybe looking at e.g. betaflight can give you ideas.

ryannining commented 6 years ago

hi, i have make 3d board and firmware for stm32 (tested), you can check github/karyacontroller it still use bresenham, but use a step buffer which contain only which motor to step and the delay from last step.

The firmware can be compiled and run on ESP8266 (using shift register), Nano 328p is the lowest mcu, since it need minimum 25kb

For STM32, i am sure it have much room to make the configuration editable without recompiling (currently using EEPROM for storing motor step configuration, acceleration, etc).

And its not use ISR TIMER for now (it have timer work but only for AVR for now).

image

hg42 commented 6 years ago

I think many things can be copied from other implementations (GPIO, ADC, etc.).

Main challenges for klipper are:

hg42 commented 6 years ago

btw...

Most libraries (mbed etc.) don't support a tickless timer or low level features like compare registers to implement this in a portable way. It's not very difficult to implement this on a CPU level, so it's not a real deal breaker. Interesting are libraries that provide usb serial and other higher level functionality, that is difficult to implement. There are a lot of similarities, because several bigger CPUs are ARM based. I would really like a target like mbed instead of one for each CPU. Especially because there are lots of STM32Fxxx and LPCxxx etc. which could be abstracted away by such a library.

KevinOConnor commented 6 years ago

FYI, I've looked a little bit at this as well. There's a lot of options in this space - here's a list I came up with:

Of these, I'd say NuttX looks the most promising to me. Unfortunately, the NuttX build is not great - when I last tried, I got weird compiler errors just trying to build their demo code for the Due. That said, NuttX seems to have support for all the interesting boards and the NuttX license is sane (which is not a given in this space - for example, the mbed license stuff scares me).

I think it's worth noting that Klipper doesn't really need that much from external libraries. There's only a few areas that I think it would offer significant help:

There are some areas where external libraries may help, but likely isn't a requirement:

There are some areas where I think Klipper would likely have to write directly to the hardware for any kind of meaningful performance. So, these I think would not be something that Klipper would use in an external library:

hg42 commented 6 years ago

One advantage of an RTOS like platform could be to program totally portable. Write once and run on all supported targets. Unfortunately nearly all libs/RTOSes are missing tickless timers (or compare register abstraction).

A good library could be written in a way that most is compiled and optimized down to direct register access (and I think some will do). Unfortunately the one with the best support for targets and devices (NUTTX) has several layers and I think it will not really compile down to bare metal. But, up to now I didn't really check this or make any speed tests. A good compiler (like gcc) may be able to optimize everything away if the parameters are constant.

When I tried to use NUTTX with LPC1768 I also got some compile errors but it was my own fault (compiler versions etc.). However, for LPC1768, I had to fix baudrate calculation, because my boot loader leaves the fractional divider register loaded which wasn't expected by the nuttx code. I generally thought, the whole system is way too big for klipper. You have to choose so many options and it's even difficult to get a simple program up and running, if it is not very similar to an example. But this would be a deal breaker if done only once.

I am not sure if the communication code can be called simple. I found there are some pitfalls. At least for LPC1768, while I finally got the UART code up and running (after learning some things about what klipper wants), the USB code still doesn't work reliably. I stopped this temporarily... @KevinOConnor when I get back to it, I will probably like to talk a bit with you about this.

grigorig commented 6 years ago

I have an STM32 (F103 only at the moment) port working, see my PR: https://github.com/KevinOConnor/klipper/pull/272

Regarding the discussion about RTOS vs no RTOS and whatever: I think it's a bit over the top to use a "big" RTOS like NuttX for Klipper. These RTOS want to provide a "real OS"-like stack on microcontrollers, which includes networking, disk I/O with filesystems and a lot more. All of these things are not needed by Klipper. So the custom scheduler seems just fine. And as you can see here, just using the basic "LL" API of STM32 HAL got me a port working in the better of a day.

hg42 commented 6 years ago

@grigorig nice, I'll certainly try your port (may take some time).

You are right, a port to a single CPU can be easy.

On the other hand you have to start a new port for every CPU someone might use. And each CPU has other challenges.

My hope was, that a library that already manages to unify several targets might allow to implement all these targets in one turn. Of course, there still might be more optimized ports for single targets.

It's not a real problem that some RTOS/library might have too much functionality. Just don't use it. You could even use only the lower level of such a beast, ignoring the rest. The power is the unification of a bunch of targets.

But indeed, there's not much hope to find a candidate that could fulfill these expectations.

archi commented 6 years ago

Great news @grigorig :) That's basically what I thought of when starting the topic. This took you one day? Reminds me I should get more practice with ES (I think I needed two days, until I hit a wall due to stm32duino crap). Once my electronics stuff is unpacked and put into its new place (moved to new flat with my gf*) and I printed my backlog I think I'll tackle swapping the electronics again.

What board are you using (besides the STM32F103)? Or did you just breadboard it? I have a rudimentary PCB layout, but still need to have a friend check the high current part of it...

Edit: Regarding the RTOS topic: Maybe we should split the issue in two? These are basically two topics and overview-wise it's probably better to discuss these in two separate github issues. I think that's pretty detached from the STM32 port anyway (since on a higher level the discussion holds for any port) and more-so now that there is port PR for the specific target of this issue.

grigorig commented 6 years ago

Took me a day to get basic functionality working, but longer to fix bugs etc. I'm using my own basic mainboard on some solder breadboard. Not great, but worked OK for testing, as you can see in the photo I linked in #272.

This was also an oportunity for me to learn the hard way that there are fake A4988 stepper driver chips. I have a number of cheap Pololu-style stepper driver modules that have chips labeled as A4988. In fact they are HR4988, a clone. HR4988 has pretty bad and noisy microstepping.

In the end, it was all good however. HR4988 have an 1/128 microstepping mode which allowed me to test high step rates in practice. :)

KevinOConnor commented 6 years ago

I'm going to close this issue as the original topic of the issue (support for STM32F1xx) is now complete and merged. I understand there is a bigger question on what frameworks could be reused, but it doesn't seem like we're any closer to consensus on that topic.