czwartek, 17 listopada 2011

ARM GCC Toolchain for Linux - Part 2.

Part 1.


IDE.
We'll use Eclipse. You can download it from www.eclipse.org. Be sure you choose the "Eclipse IDE for C/C++ Developers". Current release is Indigo. Eclipse does not require installation just un-tar it to the desired destination. Run Eclipse, enter path to the workspace, be careful it must not contain any whitespaces due to compiler problems. Mark that it's the default destination and confirm. On the next screen choose Workbench. Create a new project: File->New->C Project name it, choose the type: (Makefile project > Empty Project > -- Other Toolchain --) and click Finish. Before doing anything go to Project and unmark: Build Automatically and in Project->Clean unmark: Start a built immediately.

Let's tell Eclipse the path to Codesourcery's. Project->Properties->C/C++ Build->Settings chose GNU Elf Parser and input paths to specified files, e.g.:
/opt/sourcery/bin/arm-none-eabi-addr2line
/opt/sourcery/bin/arm-none-eabi-c++filt

There is a problem in Eclipse Indigo with system environment variables. We need to specify a path on our own. Project->Properties->C/C++ Build->Environment->Add name it "PATH". As the value put semicolon spaced paths to binutils and CS's compiler. Mine value looks like this:

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/sourcery/bin

Eclipse + OpenOCD + GDB.
To get it work we need two plugins. You can install add-ons with Help->Install new software.

The first one is "Eclipse C/C++ GDB Hardware Debugging". Go to Help->Install New Software. Input download directory to the proper dialog:
http://download.eclipse.org/tools/cdt/releases/indigo/
CDT Optional Features -> C/C++ GDB Hardware Debugging click Install.

The second one is Zylin. Download directory: http://opensource.zylin.com/zylincdt
select "Zylin Embedded CDT" click install. A couple months ago Zylin repository was abandoned but now everything seems to work well.

Running OpenOCD with Eclipse.
You can run external tools with Eclipse with one click of a button.
Run -> External Tools -> External Tools Configurations -> New
Name it depending of your config. IE: "JTAG-Pick-Lock + OpenOCD 0.5 + STM32"
Enter the path to OpenOCD. Mine is:
/usr/local/bin/openocd
Arguments:
-f interface/jtagkey.cfg -f target/stm32f1x.cfg
When finish click "Run".

The final step is creating a debugging profile, so you can enter debugging mode just with a click of the bug button. Go to:
Run -> Debug Configuration

Create a new configuration by double-clicking "GDB Hardware Debugging".Configuration is bounded to the project. You need to specify path to your project and specify executable that will be debugged. Last thing to do in this tab is changing GDB (DFS) Hardware Debugging Launcher. Click select other, mark "Use configuration specific setting" and choose "Standard GDB Hardware Debugging Launcher"

Go to tab named Debugger and specify path to CS's GDB. Mine path:
/opt/sourcery/bin/arm-none-eabi-gdb

Find a dialog box called "Port number" and enter value 3333

Go to tab Startup, unmark "Reset and Delay", unmark "Halt". Enter initialization commands to the dialog:
monitor reset halt

Mark "Set breakpoint at:" and enter
main
to the associated dialog.

Mark "Resume".

This is it. To start your debugging session click "Debug".
Have fun!

środa, 16 listopada 2011

ARM GCC Toolchain for Linux - Part 1.

This post is inspired by Freddie Chopin's tutorial showing how to install and configure a free IDE for programming/debugging ARM chips with no output limit. It's available on www.freddiechopin.info Since it's for Windows, a bit outdated and in Polish I decided to brief it here.

IMPORTANT UPDATE (17.02.2013): After completing reading the tutorial, before downloading any software please go to page http://www.freddiechopin.info/en/articles/35-arm/87-bleeding-edge-toolchain-o-co-chodzi and consider using Freddie's toolchain instead the one from CodeSourcery (Mentor).

System: Debian Squeeze 2.6.32-5-686.
JTAG-Pick-Lock (Amontec JTAG-Key)
Target: STM32

We'll be using Eclipse as IDE, Sourcery G++ Lite as toolchain, OpenOCD as debugger.

Codesourcery
Download from http://www.mentor.com/ Search for "Sourcery G++ Lite for ARM EABI". Since it's a bit tricky to find it, here is a direct link for current release: https://sourcery.mentor.com/sgpp/lite/arm/portal/release1802

Install with:
$ sudo sh

The installer will ask if you want to modify PATH. Confirm this. After installation check if it succeed. Create file main.c with simple code:


int main(void)
{
return 0;
}

Try to compile it with:
$ arm-none-eabi-gcc main.c

If you get something like:
/opt/sourcery/bin/../lib/gcc/arm-none-eabi/4.5.2/../../../../arm-none-eabi/bin/ld: warning: cannot find entry symbol _start; defaulting to 00008018

and compiler outputs file a.out everything should be ok.

IF your system PATH still isn't updated you need to edit /etc/profile. Add
export PATH=$PATH:/your/path/to/sourcery/bin
to the file. Go back to previous step to check if everything works.

OpenOCD
Current version of OpenOCD is 0.5.0. Download it form http://openocd.sourceforge.net/

Jtag-Pick-Lock (Amontec Jtag-Key) is FT2232 based. Basically you have to install libftdi-dev and compile OpenOCD with:
$ sudo ./configure --enable-ft2232_libftdi --enable-usbprog
$ make
$ make install

Smooth and easy. Check if it installed correctly:
$ openocd --version

Check if it works:
$ sudo openocd -f interface/jtagkey.cfg -f target/stm32f1x.cfg

OpenOCD should respond like this:


Open On-Chip Debugger 0.5.0 (2011-11-15-22:39)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.berlios.de/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'
1000 kHz
adapter_nsrst_delay: 100
jtag_ntrst_delay: 100
cortex_m3 reset_config sysresetreq
Info : clock speed 1000 kHz
Info : JTAG tap: stm32.cpu tap/device found: 0x3ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x3)
Info : JTAG tap: stm32.bs tap/device found: 0x16410041 (mfg: 0x020, part: 0x6410, ver: 0x1)
Info : stm32.cpu: hardware has 6 breakpoints, 4 watchpoints


If it does work, you need to add a rule that will allow regular users to use the dongle. Create a file:
/etc/udev/rules.d/45.jtagkey.rules
that contains:
SYSFS{idVendor}=="0403", MODE="666", GROUP="users"
(vendor depends on JTAG you use). Save and add your user to the chosen group.

Now you can debug from regular user's account, yay!

czwartek, 22 września 2011

How simplest EFI works.

Let's start from scratch. How the engine works.

We'll consider a four stroke spark ignition engine. Fuel contains energy. By burning fuels we release energy from fuel. Burning fuel is hot - therefore we release the energy on the way of heat. A combustion engine is a machine, that converts energy that fuel contains, into work. To do that we need to put a mixture of fuel and air into the engine, compress it and ignite. Exploding mixture will push the piston. In a four stroke engine, the whole cycle is done in two crankshaft revolutions. It goes like this:
  1. Intake. The intake valve opens (thanks to the camshaft). Fuel and air mixture is sucked into the cylinder while the piston goes down. At the end of a intake stroke the intake valve closes.
  2. Compression. Both intake and exhaust valves are closed. The piston goes up compressing the air-fuel mixture. Before the piston reaches the top dead center (TDC), spark plug ignites the mixture.
  3. Work. Combusting mixture pushes the piston down. That's how force is generated. Naturally both valves are closed.
  4. Exhaust. Burned fuel converts into exhaust gases. We need to remove them before the new cycle beginns. Exhaust valve opens and the piston goes up pushing exhaust gases out.
How is the air fuel mixture created? 
Few years back carburetor did the job. Nowadays fuel is sprayed by injectors to the manifold, where it mixes with the air. What the EFI does is calculating time of opening fuel injector. The longer it sprays, the more fuel goes into the cylinder.

There is an important parameter called AFR. It means "Air Fuel Ratio". Petrol AFR is 14,7. That means that 1 mass unit of fuel needs 14,7 mass units of air to burn completely. Basically AFR higher than 14,7 is lean mixture, lower than 14,7 is rich mixture.
  • The lean mixture gives a better fuel efficiency. When the amount of oxygen exceeds the needed value to complete burn, petrol particles can find oxygen particles easier. There is a great chance that all particles of petrol will be burned therefore we get good fuel efficiency. However there is no way that all the oxygen particles burn so we get less power. Combusting lean mixture generates more heat. It is dangerous for the engine. The other danger thing is knocking. It occurs earlier on lean mixtures.
  • The rich mixture gives more power. There is more fuel than could be burned by the amount of oxygen in cylinder so there is a great chance, that all air will be burned. We use all air in cylinder in order to produce a maximum output. Rich mixture burns in lower temperature (I'll probably cover this in future) - which is very desirable, furthermore the possibility of knocking is minimized.
  • Stoichiometric mixture (AFR = 14,7)  is a compromise between the rich and lean mixture. The oxygen sensing in exhaust gases can be used to help keeping stoichiometric AFR.
Ignition.
Air fuel mixture is ignited by spark plug. Basically mixture is ignited before TDC. It takes a while before mixture burns out. In order to get highest pressure in the optimal point of crankshaft revolution we need to ignite it before TDC. (In some cases of huge load, spark advance must be retarded to near of TDC). The more spark advance we apply, the more power and better fuel efficiency we get, but igniting to soon results in detonations (knocking). 

In the old, mechanical ignition systems there was a fixed point of ignition. Nowadays electronic circuits can modify the spark advance on the fly depending on conditions.

So what does the engine controller do?
The simplest controller just controls amount of fuel and spark advance. Basically:

  • The more load, the more fuel.
  • The more rotation speed, the more fuel.
  • The more load, the more spark timing retardation.
  • The more rotation speed, the more spark timing advance.

Maps.
Information about injection time and spark advance are stored in maps. In most cases these are 3D maps that show a function of chosen parameter in domain of load and engine speed. Now we know how it works, don't we? ECU measures engine speed and load, checks values in maps and sets proper injection time and spark advance. But how to measure engine speed and load?

RPM - Engine speed.
There are two common ways of measuring engine speed. The first way utilizes magnetic induction while the second one utilizes Hall effect. In both cases sensors are attached near to a sprocket wheel which spins dependently to crankshaft (in most cases it's attached to camshaft). When a tooth passes the sensor, it generates an electrical signal. The ECU measures time between the signals and simple computing gives time that one revolution takes and later number of revolutions per minute.

Load.
Engine load depends on how much air fuel mixture goes into the cylinder. Simply - the load is controlled by the throttle. The wider it opens the more load gets to the engine and the engine load increases. How to measure volume of air getting to the engine?

  • You can measure air velocity. Engine load depends on air mass velocity. Air velocity and it's density is measured by thermo-anemometer, so called MAF (mass airflow sensor).
  • You can measure absolute pressure in manifold. When the throttle is closed in manifold arises big under-pressure, when throttle is wide opened under-pressure almost disappears.  Knowing the value of absolute pressure and air temperature in manifold, we can predict what mass of air can get to the cylinder. MAP (manifold absolute pressure) sensor converts value of absolute pressure to an electrical signal, that ECU can interpret.
Seems simple? Yay, it is. But in fact these aren't all things ecu must know to work properly.

Crankshaft position.
ECU must know when the piston reaches which position and in which cycle, so it can decide when to start the fuel injection and when to ignite the spark. Position is measured similarly to the engine speed and it can be measured with the same device - a sprocket wheel and a sensor. Difference between speed and position measuring is that the speed must be measured a few times per revolution (RPM can be suddenly changed - that's why there are many teeth on the wheel). But the ECU couldn't figure position from a regular sprocket, that's why one tooth is removed from the sprocket wheel. When the sensor passes larger space between teeth than regular one, ecu knows that it just passed a determined position. Now figure out why "positioning" sprocket must be attached directly to the camshaft and not the crankshaft?
Answer: crankshaft spins two times every time the camshaft makes one spin.

poniedziałek, 19 września 2011

Embedded programming - how to choose a target processor

Purpose of this blog is not a step by step tutorial, therefore I won't make a tutorial about uC's programming (besides I'm a beginner as well). If you want to program uC's I'll give you some advices:
- First of all, don't ask me or communities questions like: "What's a debugger". Most questions are answered thousands times, you just need to do the search, if you ask, you'll just be another lazy, annoying newbie.
OK. Real advices:
- Learn C programming language, its simple and efficient. "ANSI C" by Brain Kernighan and Dennis Ritchie is a good point to start. Go through this book before buying a MCU dev kit.
- Find out which uC suits you best:

  • Atmel's AVR is very popular, there is a lot of support, there is a free IDE (from Atmel?): Avr Studio (C, ASM, C++), programmer devices are simple and cheap, there are tons of sample projects, schematics, examples on the internet. A great advantage is BASIC compiler for most AVRs (called Bascom). BASIC is a great programmer's time saver in some applications, but in some cases produces slow and large output. Bascom isn't free, but there is some kind of evaluation. Avr is an 8bit uC. And it's good for beginners. Cont's of AVR:
  1. Atmel for unknown reasons, discontinued for a couple of month's production of world's most popular hobby MCU's. That increased AVR's prices incredibly. Atmel is an unreliable manufacturer.
  2. Programming devices are cheap and simple, but programming-debugging devices are quite complicated and aren't that cheap. You will need a debugger sooner or later.
  3. To be honest AVRs are becoming out of date.
  • On the other hand very popular are MCUs based on ARM core. These units are 32bits, have tons of peripherals and are a nightmare for beginners. Most manufacturers don't provide a free IDE, some have very poor support. If you choose an ARM based MCU, you should have some knowledge about uC's. Debuggers are very expensive and in fact essential. If you already know something about programming, choose it. (Later you'll have to choose between the manufacturer and between core version).
  • My advice for beginners is to choose Texas Instruments MSP430 16bit uC's. It's cheap - search for TI Launchpad dev board, this board has an integrated programmer-debugger. TI provides an Eclipse based IDE that is limited to 16k output code, but 16k is quite a lot of code. Bet you won't be able to fill a 2k space for a long time ;) MSP430 has a big community, a marvelous and clear support, you don't need anything else. TI is an excellent choice for a beginner.
  • There are many other kinds of MCU's. Microchip PIC and Motorola are very popular, but I have no experience about it. Worth mentioning is that there are thousands kinds of PIC's and that Megasquirt is based on Motorola MCU.
  • Summary: ARM based uCs seem to be the future in very advanced systems. TI offers a variety of MSP430 uCs from simple units to quite powerful ones.
- Get familiar with Assembler. It's useful. I don't mean, try to write complicated algorithms in ASM, just get familiar with it's commands and syntax. It will help you figure out how MCU works.

My gear:
  • TI Launchpad MSP430 + CCS
  • ARM Cortex M3 STM32 (STM32F103RBT) Attached to a simple dev board with fancy TFT Touch Screen (which I haven't used once ;). I must warn you, that ST provides awful and poor support. Perhaps NXP or TI would be a better choice - I'll consider this if I need a change.
  • A simple DIY contact board with couple of switches, a 2x16 HD47780 Lcd and transistors attachable for both TI and STM32 devboards.
  • ARM programmer-debugger: A copy of Amontec JTAG-Key.
  • IDE: Eclipse + Codesourcery Toolchain + OpenOCD. Very useful and totally free with no limitations.
I think that's all for today.
Cheers.


Update:

Recently I got a new devboard from ST STM32F4 and a copy of TI's BeagleBoard - DevKit8000 equipped with a Cortex A8 processor. It's a powerful processor with a huge core designed to run under control of an OS rather than bare metal like other MCUs I mentioned in this post. I am trying to make use of it.

Hello World!

Hi, I am a student of Mechanical Engineering. Issues of combustion engines control bothers me a lot so I decided to try to gain some knowledge by building an electronic engine control unit. I'll keep the project open and share experiences here.

There is already an open efi project (Megasquirt), but I think, that learning on my own mistakes is much more fun.

If you find any mistakes or have any remarks, please leave feedback.