I am a software developer (using high level languages like .NET,C,C++ etc) trying to understand how computers work at a lower level.

I have asked questions like the following in the past and got some useful responses: Map processor to circuit diagram. I have bought an Adruino board to help me.

What other hardware do low level gurus buy to learn more about hardware and lower level programming? Would a Raspberry Pi be helpful (I believe they are targeted at children). Also I was thinking about buying a tablet.


How "low" do you want to go?

The standard Arduino IDE is not really for low level programming. You have ready-to-use libraries with high level interfaces, you don't really have to care about correct SFR initialisation, memory layout and other details.

Raspberry usually has a Linux OS running, and you develop very "high leveled". It's a powerful and flexible system, by far not only for children, but it's surely not the best solution to start with when you want to understand the lower levels of a computer.

My suggestion, as you already have an Arduino: Study the microcontroller's datasheet and use the standard Atmel IDE instead of that high level Arduino development stuff. Start programming it in assembler instead of C. This is really low level fun :-)

If you want an even lower level, go for FPGA design. Try to get a softCore library, learn VHDL, and you can examine practically and very detailed what's going on in a CPU.

  • \$\begingroup\$ Can you answer my question in the comment above? Then I will tick your answer. \$\endgroup\$ – w0051977 Nov 28 '14 at 12:50
  • \$\begingroup\$ A "softcore library" is the source code (usually in VHDL or Verilog) of a CPU. Load it into a FPGA and you can use it like a CPU. There are some free libraries available: en.wikipedia.org/wiki/Soft_microprocessor \$\endgroup\$ – mic Nov 28 '14 at 14:22
  • \$\begingroup\$ +1, do you know if there is one for arduino? \$\endgroup\$ – w0051977 Dec 4 '14 at 14:37
  • \$\begingroup\$ There's an AVR implementation on OpenCores: opencores.org/project,avr_core \$\endgroup\$ – mic Dec 4 '14 at 15:15
  • \$\begingroup\$ It's not for the one used on the Arduino boards, but CPU and architecture should be similar/the same as for an ATmega328 (Arduino Uno) \$\endgroup\$ – mic Dec 4 '14 at 15:39

No, Arduino or Raspberry Pi aren't for low level programming. These come with libraries and other existing software whos job is to avoid you getting at the low levels.

To really learn how a processor works by executing machine code, start with a bare processor and write in assembly language. A small PIC 24 in 28 pin package is a good place to start. These come with internal oscillator, so all you need is to hook up the power and ground pins, bypass caps, and pull MCLR high to bring the hardware up to where it will run code. The instruction set is very well documented, and the assembler, linker, IDE, etc, are all available via free download from the Microchip web site.

Actually, you don't need hardware at all initially. The MPLAB IDE comes with a simulator, which is actually a very nice debugging environment. Get a simple program up and running in the simulator first. You will be able to single step thru it and see exactly what all the registers are doing. You can even give it simulated inputs and see what it does with them. Once the program is working in the simulator, you can try it on a real chip.

You will need some sort of debugger/programmer to get the program into the real hardware. The professional in-circuit debugger is the RealIce, but I have heard that the PicKit-3 is a workable low-cost alternative, although I haven't personally used it.

  • \$\begingroup\$ You're not limited to using the libraries to get to the bare hardware in Arduino -- you can program in either C or assembler (assembled as separate .s files, just like the PIC). As you know from my other answers, I'm a PIC person myself -- but the ATmega processors do have some nice features. I'll agree though about the Raspberry Pi -- I have one of those, along with a BeagleBone Black and an Arduino Mega 2650, and the first two, running Linux are nowhere near as fun. \$\endgroup\$ – tcrosley Nov 27 '14 at 19:20
  • \$\begingroup\$ A RaPi can be programmed bare-metal, and it is not that difficult. It exposes a lot less pins than a typical micro-controller, but the amount of memory is awesome. \$\endgroup\$ – Wouter van Ooijen Nov 30 '14 at 18:18

If you already have an Arduino, I would stick with that -- it's going to be a lot more understandable than the Raspberry Pi, which is essentially a little desktop running Linux in a very small form factor.

Whereas with the Arduino, the whole system is simple enough one can get their head around it.

You didn't say which Arduino you have, but in any case you should find out which ATmega processor is on your board and then download the datasheet for it. Don't download just the summary, download the full datasheet will be several hundred pages long. For example, here is the datasheet for the ATmega328, which is the microcontroller used in the Arduino Uno.

While not necessary for programming the Arduino in its Sketch version of C++ (I suspect few Arduino owners have taken the trouble to download the datasheet, or even know one exists), reading through it you will get an idea of what is inside the microcontroller.

A microcontroller like the ATmega is much more than just a CPU -- it has programmable flash memory, RAM, EEPROM, a lot of I/O including parallel ports, serial interfaces (UARTS, SPI, I2C), and a ADC (analog to digital converter), and timers. There will be a separate section in the datasheet for each of these topics.

Don't expect to understand everything -- or even very much at all to begin with. However being a high-level language programmer, you will probably be interested in the various internal registers including the 32 general purpose registers and how they are used, the various addressing modes (there are several, some quite complex), and what the instruction set looks like.

For example, there is an addressing mode -- "indirect data memory addressing with post-increment" -- that allows a C++ reference like *x++ to be implemented in one instruction.

If you have never done assembly language programming, looking at the registers, instruction set, and addressing modes will give you a feel for what it is going on inside at that level.

Then take a lot at all of the sections describing I/O on the ATmeaga. For example looking at the description of the GPIO ports for the ATmega will give you a better idea of that is going on when you use the pinMode and digitalWrite / digitialRead calls for example. You might want to buy some additional shields for your Arduino so you can experiment doing various kinds of I/O.

Although buying a tablet is a good idea for many reasons, it's not going to help you understand how a computer works at all.

Like other small microcontrollers, for example PICs, it is possible to get down to the bare hardware on an Arduino board -- just think of it as an AVR development board. You don't have to use any of the libraries if you don't want to.

For example, to read and write the ports, you can use the instructions:

DDRB = 0x01;    // set data direction register for port B to output
PORTB = 0x01;   // set bit 1 of PORTB

Essentially, you are now programming in pure C, not C++. Here is more information on programming the Arduino in C.

If you don't like the Arduino IDE, you can program in either Visual Studio or Atmel Studio IDEs.

If you want to really get down to the hardware, you can program in assembly language using the instructions in the datasheet you downloaded earlier. Google "arduino programming in assembler" (without the quotes) for lots of links about this topic.

Here is a one-hour tutorial on YouTube about programming the Arduino inn assembler.

And here is some example code -- a subroutine for turning an LED on and off in assembler:

#include "avr/io.h"
#include "asmtest.h"

.global asminit
sbi  4,5; 4 = DDRB (0x24 - 0x20). Bit 5 = pin 13

.global led ; The assembly function must be declared as global
cpi r24, 0x01 ; Parameter passed by caller in r24
breq turnoff
sbi 5, 5; 5 = PORTB (0x25 - 0x20). Bit 5 = pin 13
cbi 5, 5; 5 = PORTB (0x25 - 0x20). Bit 5 = pin 13

which is assembled as a separate .s file. The complete code for the Arduino blink LED example in assembler, showing use of several of the Arduino's 32 general purpose registers, can be found here.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.