Traumflug / Teacup_Firmware

Firmware for RepRap and other 3D printers
http://forums.reprap.org/read.php?147
GNU General Public License v2.0
312 stars 199 forks source link

Generic ARM port #171

Open Traumflug opened 9 years ago

Traumflug commented 9 years ago

Today I finally(!!!) managed to return to the ARM port. All other ports so far use some custom library or another, this one shall be independent. And, of course, it must not break support for ATmegas.

First steps are done, all on the gen7-arm branch. This commit: https://github.com/Traumflug/Teacup_Firmware/commit/921b55ca322aa600c2444180b59dda6db35d23b4 shows how putting architecture dependent code in distinct files can work without breaking Arduino IDE support. Especially this part is the key (example from serial.c):

#define TEACUP_C_INCLUDE
#include "serial-avr.c"
#include "serial-arm.c"
#undef TEACUP_C_INCLUDE

Then you can simply wrap all the contents in the arch-specific file:

// AVR-specific file:
#if defined TEACUP_C_INCLUDE && defined __AVR__
[...]
#endif
- - - -
// ARM-specific file:
#if defined TEACUP_C_INCLUDE && defined __ARMEL__
[...]
#endif

and it works in all cases. Tested with Arduino IDE, Makefile and Configtool. Just Arduino 1.0.5 didn't like it, for some reason it copied only some, but not all files over to its temporary build directory. Arduino 1.5.8 was fine.

Current state of the port is: it builds (Makefile only) a basic binary with Teacup sources, next step is to get the uploader in place, then setting up the PLL, then getting serial running. After that it's a piece of cake.

jgrjgr commented 9 years ago

fantastic, so would the same arm code potentially work between say the arduino due which is stm32 and say the lpc1768 thats on the smoothieboard ?

triffid commented 9 years ago

There would need to be some sort of HAL to select and interface with each chip's differing startup code and peripherals.

The major parts of Teacup are already quite chip-agnostic, although I believe it might be sensible to use real floats on ARM rather than teacup's float implementation.

Teacup has already been ported to ARM multiple times, but never in collaboration with upstream which is why this is (finally) exciting news!

Traumflug commented 9 years ago

so would the same arm code potentially work between say the arduino due which is stm32 and say the lpc1768 thats on the smoothieboard ?

That's the goal: copy in the MCU specific files from CMSIS, adjust a few #defines, then it should work.

I also thought about using MBED, which is a library similar to the one coming with Arduino IDE. The Hello World example, also in this branch, uses it. Pretty bloated. For example, the function for setting the baud rate takes some 2.5 kB. A task which writes a register or two. All calculations are done at runtime, zero preprocessor math.

I believe it might be sensible to use real floats on ARM rather than teacup's float implementation.

Maybe for the larger ARMs. The LPC1114 on my desk is a Cortex-M0 and has no more float capabilities than an ATmega. Even for chips with hardware float I see currently not much use for them other than perhaps the Scara variant, which needs sine and cosine.

Teacup has already been ported to ARM multiple times, but never in collaboration with upstream

If I just knew how to encourage people to do this kind of collaboration. Sure, it can be tedious to review already working code over and over again just to get it tidier, to not break other boards. Often thought about dropping this nitpicking and simply accept whatever comes in. Can't imagine this lasts for long, though, soon there would be more regressions than advantages.

That said, I expect these ports to help immensely. They solved many tasks in the upper layers already, so I can simply copy this stuff.

Traumflug commented 9 years ago

Perhaps it's time for an update. Just pushed my current work branch, gen7-arm.

Getting serial working was less hassle than expected, I simply copied it from the low level parts of MBED. This added 24 files and bloated the code from 944 to 5956 bytes. Since then I replace with smaller code piecewise, I'm down to 1624 bytes, serial still working fine. What else happened?

So it can read and write pins. It uses bit-banding by address mapping, which is expected to be the fastest way to operate single bits. Turning a pin on and off without anything in between can create spikes of just 64 nanoseconds, so 3 clock cycles (measured with the scope). Even when the compiler optimiser messes up, it's still 5 clocks. Tried also with MBEDs GPIO implementation, which takes no less than 1500 nanoseconds or 72 clocks for the same task.

Next steps are to further clean out this MBED stuff. Then there's not much holding back from getting G-code reading and stepper motor movement working.

Traumflug commented 9 years ago

Hint on pull request #178.

Traumflug commented 9 years ago

Good. Just pushed my current work to gen7-arm. New since the last push:

For the latter I have a question: how should Teacup name pins on ARM boards? Currently it's _PIO00, _PIO01, _PIO02, and so on, because the NXPs User Manual happens to use these names. No problem to change that to DIO1, DIO2, ..., but which mapping should be used without an actual Arduino being present? What do the other ARM firmwares?

triffid commented 9 years ago

In smoothie we use Px.y where x is port and y is pin. direct from the datasheet.

For the arm chip on the Due you might have to use arbitrary arduino mapping, but with any other chip you can use something sensible and ignore arduino

Traumflug commented 9 years ago

Thanks, @triffid. Will stick then to data sheet names, too.

Perhaps you've seen it in the forum, steppers move. Not all quirks resolved, but they do move. Almost like AVR 8-bit, the step interrupt takes some 300 clock cycles. 288 on ARM vs. 304 on AVR, to be precise. That makes currently a maximum step rate of 128 kHz:

pic_34_2

Traumflug commented 9 years ago

Next round: analog readings implemented.

I start to like this LPC1114. No interrupt needed for the serial line, because there's a small buffer in hardware. No interrupt needed for analog readings, because the chip features a "hardware scan mode" where on can define up to 8 pins at once and hardware will switch between them in freerunning mode. After setting this up in analog_init() software has nothing further to do, just to read the results when needed. So far we have only Step and SysTick interrupts, looks like this gives a very smooth ride.

Maybe you've noticed a number of commits on experimental. Walking through the code in detail obviously brings up a few minor enhancements here and there, so I put them to experimental immediately. Some more AVR related changes on the AVR branch.

Just pushed the latest version of the gen7-arm branch. No less than 68 commits by now :-)

P.S.: steppers work fine now as well, including lookahead. "Porting" was so simple I almost forgot to mention that.

Traumflug commented 9 years ago

Just pushed the latest version of the gen7-arm branch. 76 commits.

Traumflug commented 9 years ago

Generic ARM port is done :-)

gen7-arm is 88 commits now and every single one of these passes the regression test. My local TODO list is empty regarding this port. Configtool changes are still outstanding, so far one has to use Makefile-ARM and edit the board file (config/board.gen7-arm.h) manually.

I'll let it on this branch for another few days for you to play with. Some AVR code had to be changed, too, e.g. heater/pwm setup code.

If you want to do your own port, simply repeat the same steps as the ones on this branch. It changes things in fairly easily understandable chunks, many many comments on what's done each time and how to test the new achievements. Enjoy!

phord commented 9 years ago

Curious about the TEACUP_C_INCLUDE shenanigans. Is that because the Arduino IDE will (sometimes?) only find files which are #include'd?

Traumflug commented 9 years ago

It's for the opposite: Arduino compiles everything it can find, so the code would be compiled twice ... if it compiles standalone at all.

phord commented 9 years ago

It seems a bit too overwrought to me. There doesn't seem to be much common code being used as a result of this. Where it is, it seems it could be split out; for example, heater.c's common code could be moved into 'pid.c'. Alternatively, all the cpu-specific code could be put in ".ch" files so arduino's IDE would ignore them. Or they could be put into subdirectories. "arm/heater.c" and "avr/heater.c". Arduino doesn't include subdirectories automatically which is why there is a simulator/ directory.

I did look over the rest of the changes in git diff gen7-arm experimental and I'm happy to say it looks very nice. I quite like the direction you've chosen and the cleanup you've done. Nice work!

I'm not able to build the arm code, though. At least not with make regressiontests. Can you tell me how to install a suitable toolchain? I suspect I might only be missing a reference to the mbed include path, or something like that.

Here's what I tried on Linux:

sudo add-apt-repository ppa:terry.guo/gcc-arm-embedded
sudo apt-get update
sudo apt-get install gcc-arm-none-eabi
sudo pip install colorama
git clone git@github.com:mbedmicro/mbed.git
cd mbed
workspace_tools/build.py -m LPC1114 -t GCC_ARM
cd ../Teacup_Firmware
make regressiontests
 ...
  CC        build/testcases/config.regtest-gen7-arm/analog.o
In file included from config_wrapper.h:8:0,
                 from temp.h:4,
                 from analog.c:7:
arduino.h:83:4: error: #error Pins for this chip not defined in arduino.h! If you write an appropriate pin definition and have this firmware work on your chip, please tell us via Github or the forum thread.
   #error Pins for this chip not defined in arduino.h! If you write an \
    ^
make[1]: *** [build/testcases/config.regtest-gen7-arm/analog.o] Error 1
make: *** [regressiontests] Error 2
Traumflug commented 9 years ago

Subdirectories don't work, because before Arduino IDE does its "compile everything" approach, it copies all the files into a temporary directory and compiles there. It does not copy subdirectories, so such files #included aren't found.

Renaming files to .ch would be possible, but code editors would no longer recognize the file extension for syntax coloring.

Regarding building: MBED is no longer neccessary, this was a different (and pretty complicated) approach. The few usable files from MBED are all from the CMSIS level and were copied directly into Teacup (the ones starting with cmsis-). With the compiler installed it should just work.

Now I'm wondering what's missing. I guessed you use a copy of Makefile-example as Makefile and tried this. Near the top of this file there are these two lines:

export F_CPU = 20000000L
export MCU = atmega644p

These obviously don't fit for an ARM. Commenting them out makes regression tests work here. Changing them to this:

export MCU = lpc1114

makes it working as well. F_CPU is unused in Makefiles for ARM; defined in one of the CMSIS files depending on the PLL parameters choosen.

All this said, for the next ARM flavor, e.g. the SAM chips on the Arduino Due, it might be a good idea to rename all the *-arm.c files to -lpc.c and to introduce -sam.c as well. Glancing over code for these chips I see that all the registers are named entirely differently and probably also work differently. "ARM" means just the core, the Cortex-M0/3/4, but not "peripherals" like UART, GPIO, ADC, etc.

triffid commented 9 years ago

In one of my experiments with HALs, i set up a structure where the mcu selection would cause the Makefile to include a whole directory of files specific to that mcu.

It might be easier than renaming and copying files every time you support a new mcu, as "ARM" is a pretty wide field!

Traumflug commented 9 years ago

It might be easier than renaming and copying files every time you support a new mcu, as "ARM" is a pretty wide field!

You have to copy files anyways. My first steps used MBED and the CMSIS inside it. I ended up with 8 or 10 -I flags for all the required levels inside MBED. Copying 4 or 6 files is simpler and requires zero -I flags.

Whatever. No major complaints, so I forwarded master to experimental of yesterday and experimental to what was gen7-arm. Branch gen7-arm removed, ARM LPC1114 is now an official target. Thanks for your help :-)

Traumflug commented 9 years ago

Also added a tag arm-ports-start-here for those who want to use these 87 commits as kind of a tutorial to do another ARM port. I hope I find time to write a bunch of instructions into the RepRap wiki on how to do this.

Traumflug commented 9 years ago

I hope I find time to write a bunch of instructions into the RepRap wiki on how to do this.

Here we go: http://reprap.org/wiki/Teacup_Firmware#Porting_to_other_.28ARM-_or_non-ARM-.29platforms

phord commented 9 years ago

Right. Subdirectories are good for code you don't want the Arduino IDE to use. I forgot that.

Also right about the reason for my failed build. I moved the MCU setting deeper in my Makefile so it does not affect the regressiontests target, and now the tests all pass.