Do you have a question? Post it now! No Registration Necessary
April 10, 2006, 3:41 am

Excerpted from AVR Butterfly Site at: http://retrodan.tripod.com
VON NEUMANN vs. HARVARD ARCHITECTURE
If you are new to Microcontrollers one of the arguments you are going to
hear bantered about is Harvard Architecture versus the Von Neumann
Architecture.
THE VON NEUMANN ARCHITECTURE
Most computers we are familiar with use an architecture called Von Neumann.
The term arose out of Neumann's 1945 draft report on the ADVAC computer. He
was not, however the original inventor of it.
+---------+
| RAM |
| - - - - |
BottleNeck | PROGRAM |
[CPU] <==========> | - - - - |
| DATA |
+---------+
A Von Neumann machine has one large monolithic RAM structure that contains
both program memory and data memory mixed together. Since both program steps
and data must be loaded from the same place, it can create a problem called
the Von Neumann Bottle-Neck.
THE HARVARD ARCHITECTURE
Most microcontrollers use a different system called Harvard architecture.
The larger program storage and the smaller data memory are separated. The
first such machine, the Harvard Mark I had it's programs hard-coded on
paper-tape and the volatile data was loaded into electric relays.
+----------+ +------+
| PROGRAM | | DATA |
| ROM | <----> [CPU] <----> | RAM |
+----------+ +------+
Harvard style machines allow program steps to be fetched at the same time as
data, thereby creating potentially faster through-put and less of a
bottle-neck. They also have the benefit that run away processes can't damage
the program stored in the non-volatile program area so they're more stable.
Many C programs lack proper boundary checking and a null pointer or an
over-run buffer can overwrite and crash a program that shares RAM with data.
If you are new to this architecture you need to keep this in mind. When
creating a routine that needs a few bytes of storage, I would normally
create that space within the routine itself. On a Harvard machine, those
bytes would not be in volatile RAM but part of the hard coded program memory
stored in ROM (or FlashRAM).
AVR BUTTERFLY PROGRAM SPACE (FLASH)
The AVR Butterfly (Atmega169) program space is 16K long and is divided into
two main areas. The top 1-2K and is usually loaded with a bootloader that is
protected from an overwrite and the rest is available for your programs. At
the beginning of each program space is an area for interupt vectors. The
first such vector is the Power-Up/Reset Vector and should contain an RJMP to
the first line of your program.
.---------------------------------------------------.
| POWER-UP VECTOR (NORMALLY POINTS TO YOUR PROGRAM) |
| OTHER INTERUPT VECTORS |
|- - - - - - - - - - - - - - - - - - - - - - - - - -|
| |
| YOUR PROGRAM SPACE (14-15K) |
| |
| |
.---------------------------------------------------.
| BOOT:INTERUPT VECTORS |
|- - - - - - - - - - - - - - - - - - - - - - - - - -|
| BOOTLOADER PROGRAM SPACE (1-2K) |
`---------------------------------------------------'
AVR BUTTERFLY DATA SPACE (SRAM)
The data space on the AVRs is a little unusual. The 32 internal accumulators
are memory mapped as the first 32 bytes of data memory, followed by all the
I/O ports which are mapped into memory space followed by the 1K of actual
SRAM starting at $100.
.---------------------------------------------------.
|$00-$1F: 32 Internal Accumulator/Working-Registers |
+---------------------------------------------------+
|$20-$5F: 64 Input/Output Ports |
|- - - - - - - - - - - - - |
|$60-$FF 160 Extra I/O Ports |
+---------------------------------------------------|
|$100 |
| 1024 Bytes SRAM $100 to $4FF |
| |
| |
|- - - - - - - - - - - - - |
|$4FF (Normal Location for Stack) |
`---------------------------------------------------'

Re: VON NEUMANN VS HARVARD

[snip]
There are theories and there are actual devices that
have some performance, some features and a price tag.
At one point, when you have to actually solve a problem,
get some embedded system doing a job, then you just
compare the available devices, their prices, the
development tools and the support.
And you won't get the ultimate mega machine for
1$ a piece.
Rene
--
Ing.Buero R.Tschaggelar - http://www.ibrtses.com
& commercial newsgroups - http://www.talkto.net
Ing.Buero R.Tschaggelar - http://www.ibrtses.com
& commercial newsgroups - http://www.talkto.net

Re: VON NEUMANN VS HARVARD

In my opinion everything that uses the harvard architecture is very,
very outdated.
The main problem with the HA is that you have seperate memory spaces.
C doesn't like that. You'll have to test which memory space a pointer
is pointing to. Functions like memcpy, printf, etc, etc, won't work
with any pointer. Ofcourse you can kludge things together, but in the
end you'll find yourself locked to that target. With ever shorter
product life times you'll want to move your code to other platforms or
develop on a PC and then transfer the algorithm to an embedded device.
Modern processors use an instruction and data cache which basically
'emulate' the harvard architecture without its downsides.
--
Reply to nico@nctdevpuntnl (punt=.)
Bedrijven en winkels vindt U op www.adresboekje.nl
Reply to nico@nctdevpuntnl (punt=.)
Bedrijven en winkels vindt U op www.adresboekje.nl

Re: VON NEUMANN VS HARVARD
[....]

In my opinion everthing that uses C is very, very outdated. The C
language doesn't support the passing of or the returning of complex data
types. It is also stuck with the dangerous and silly notion of the
"pointer".
High performance processors like DSPs often have different classes of
memories. Instructions, integers and floats can all have their own
address spaces. Writing C compilers for such things is a real nightmare
and even with a good compiler writing in C is a sickening task.
--
--
snipped-for-privacy@rahul.net forging knowledge
snipped-for-privacy@rahul.net forging knowledge

Re: VON NEUMANN VS HARVARD

A pointer is as dangerous as the programmer using it. By your remark
about complex data it seems you have little experience with C. It is
not a problem to pass a pointer to complex data types or objects (most
programs do this all the time) and alter the contents. C even offers
ways to make function parameters read-only so you'll get a compiler
warning if you overwrite arguments.
Besides, modern DSPs like the Analog Devices Blackfin series have a
MMU which can be used to make certain memory areas read only. Since it
has a single address space, you can run an embedded OS like micro
Linux if you like.

Old style thinking, old style hardware. All these performance tuning
kludges can be replaced by using a cache memory which allows for
efficient code generation by a C/C++ compiler on a single memory space
CPU. Keep in mind that on CPUs with seperate memory spaces, a lot more
instruction codes are wasted which could be used for nifty things like
read-modify-write bit set/toggle/clear operations.
--
Reply to nico@nctdevpuntnl (punt=.)
Bedrijven en winkels vindt U op www.adresboekje.nl
Reply to nico@nctdevpuntnl (punt=.)
Bedrijven en winkels vindt U op www.adresboekje.nl

Re: VON NEUMANN VS HARVARD

No, a pointer is by its nature dangerous. Because of it, you have to do
all sorts of strange stuff to do bounds checking in C. In other langages,
range checking is much easier to do.

Yes, you can pass a pointer but like I said, you can neither pass not
return a complex type. You have to pass a pointer if you wish your
subroutine to work with a complex type. You seem to claim to have a lot
experience with C and yet you missed that point.
The syntax of C hides the fact that it is a pass by reference in the
call statement so you have to look at other lines of the code to know if
the routine modifies the value.

Yes and this has zero to do with the statements in my post.
[....]

The cache uses much more silicon to get the same performance. You can get
better performance by having multiple address spaces.
--
--
snipped-for-privacy@rahul.net forging knowledge
snipped-for-privacy@rahul.net forging knowledge

Re: VON NEUMANN VS HARVARD

Nonsense. It's trivially easy to pass and return structures - the only
limit is your stack size:
------------------------
/* complex_type.c */
/* to demonstrate passing and returning structures from a C function */
#include <stdio.h>
struct FourItems {
int item1;
int item2;
int item3;
int item4;
} A;
struct FourItems manipulate(struct FourItems Q) {
printf("Q.1 = %d, Q.2 = %d, Q.3 = %d, Q.4 = %d\n",
Q.item1, Q.item2, Q.item3, Q.item4);
Q.item1 = 5;
Q.item2 = 12;
Q.item3 = 3;
Q.item4 = 7;
return Q;
}
int main(int argc, char *argv[]) {
struct FourItems B;
A.item1 = 1;
A.item2 = 2;
A.item3 = 3;
A.item4 = 4;
printf("A.1 = %d, A.2 = %d, A.3 = %d, A.4 = %d\n",
A.item1, A.item2, A.item3, A.item4);
B = manipulate(A);
printf("B.1 = %d, B.2 = %d, B.3 = %d, B.4 = %d\n",
B.item1, B.item2, B.item3, B.item4);
exit(0);
}
-----------------------------
Here's its output:
$ complex_type
A.1 = 1, A.2 = 2, A.3 = 3, A.4 = 4
Q.1 = 1, Q.2 = 2, Q.3 = 3, Q.4 = 4
B.1 = 5, B.2 = 12, B.3 = 3, B.4 = 7
-----------------------------
And here's a list of the generated code:
$ cat complex_type.lst
GAS LISTING /tmp/ccQA6n9P.s page 1
1 .file "complex_type.c"
2 .file 1 "complex_type.c"
10 .Ltext0:
11 .file 2
"/usr/lib/gcc-lib/i486-slackware-linux/3.3.6/include/stddef.h"
12 .file 3 "/usr/include/bits/types.h"
13 .file 4 "/usr/include/stdio.h"
14 .file 5 "/usr/include/wchar.h"
15 .file 6 "/usr/include/_G_config.h"
16 .file 7 "/usr/include/gconv.h"
17 .file 8
"/usr/lib/gcc-lib/i486-slackware-linux/3.3.6/include/stdarg.h"
18 .file 9 "/usr/include/libio.h"
19 .section .rodata
20 .align 32
21 .LC0:
22 0000 512E3120 .string "Q.1 = %d, Q.2 = %d, Q.3 = %d, Q.4 =
%d\n"
22 3D202564
22 2C20512E
22 32203D20
22 25642C20
23 .text
24 .globl manipulate
26 manipulate:
27 .LFB3:
1:complex_type.c **** /* complex_type.c */
2:complex_type.c **** /* to demonstrate passing and returning structures from
a C function */
3:complex_type.c **** #include <stdio.h>
4:complex_type.c ****
5:complex_type.c **** struct FourItems {
6:complex_type.c **** int item1;
7:complex_type.c **** int item2;
8:complex_type.c **** int item3;
9:complex_type.c **** int item4;
10:complex_type.c **** } A;
11:complex_type.c ****
12:complex_type.c **** struct FourItems manipulate(struct FourItems Q) {
28 .loc 1 12 0
29 0000 55 pushl %ebp
30 .LCFI0:
31 0001 89E5 movl %esp, %ebp
32 .LCFI1:
33 0003 53 pushl %ebx
34 .LCFI2:
35 0004 83EC04 subl $4, %esp
36 .LCFI3:
37 0007 8B5D08 movl 8(%ebp), %ebx
13:complex_type.c **** printf("Q.1 = %d, Q.2 = %d, Q.3 = %d, Q.4 =
%d\n",
38 .loc 1 13 0
39 000a 83EC0C subl $12, %esp
40 000d FF7518 pushl 24(%ebp)
41 0010 FF7514 pushl 20(%ebp)
42 0013 FF7510 pushl 16(%ebp)
43 0016 FF750C pushl 12(%ebp)
44 0019 68000000 pushl $.LC0
44 00
45 .LCFI4:
46 001e E8FCFFFF call printf
46 FF
GAS LISTING /tmp/ccQA6n9P.s page 2
47 0023 83C420 addl $32, %esp
14:complex_type.c **** Q.item1, Q.item2, Q.item3, Q.item4);
15:complex_type.c ****
16:complex_type.c **** Q.item1 = 5;
48 .loc 1 16 0
49 0026 C7450C05 movl $5, 12(%ebp)
49 000000
17:complex_type.c **** Q.item2 = 12;
50 .loc 1 17 0
51 002d C745100C movl $12, 16(%ebp)
51 000000
18:complex_type.c **** Q.item3 = 3;
52 .loc 1 18 0
53 0034 C7451403 movl $3, 20(%ebp)
53 000000
19:complex_type.c **** Q.item4 = 7;
54 .loc 1 19 0
55 003b C7451807 movl $7, 24(%ebp)
55 000000
20:complex_type.c **** return Q;
56 .loc 1 20 0
57 0042 8B450C movl 12(%ebp), %eax
58 0045 8903 movl %eax, (%ebx)
59 0047 8B4510 movl 16(%ebp), %eax
60 004a 894304 movl %eax, 4(%ebx)
61 004d 8B4514 movl 20(%ebp), %eax
62 0050 894308 movl %eax, 8(%ebx)
63 0053 8B4518 movl 24(%ebp), %eax
64 0056 89430C movl %eax, 12(%ebx)
21:complex_type.c **** }
65 .loc 1 21 0
66 0059 89D8 movl %ebx, %eax
67 005b 8B5DFC movl -4(%ebp), %ebx
68 005e C9 leave
69 005f C20400 ret $4
70 .LFE3:
72 .section .rodata
73 0028 00000000 .align 32
73 00000000
73 00000000
73 00000000
73 00000000
74 .LC1:
75 0040 412E3120 .string "A.1 = %d, A.2 = %d, A.3 = %d, A.4 =
%d\n"
75 3D202564
75 2C20412E
75 32203D20
75 25642C20
76 0068 00000000 .align 32
76 00000000
76 00000000
76 00000000
76 00000000
77 .LC2:
78 0080 422E3120 .string "B.1 = %d, B.2 = %d, B.3 = %d, B.4 =
%d\n"
78 3D202564
78 2C20422E
GAS LISTING /tmp/ccQA6n9P.s page 3
78 32203D20
78 25642C20
79 .text
80 .globl main
82 main:
83 .LFB5:
22:complex_type.c ****
23:complex_type.c **** int main(int argc, char *argv[]) {
84 .loc 1 23 0
85 0062 55 pushl %ebp
86 .LCFI5:
87 0063 89E5 movl %esp, %ebp
88 .LCFI6:
89 0065 83EC18 subl $24, %esp
90 .LCFI7:
91 0068 83E4F0 andl $-16, %esp
92 006b B8000000 movl $0, %eax
92 00
93 0070 29C4 subl %eax, %esp
24:complex_type.c **** struct FourItems B;
25:complex_type.c ****
26:complex_type.c **** A.item1 = 1;
94 .loc 1 26 0
95 .LBB2:
96 0072 C7050000 movl $1, A
96 00000100
96 0000
27:complex_type.c **** A.item2 = 2;
97 .loc 1 27 0
98 007c C7050400 movl $2, A+4
98 00000200
98 0000
28:complex_type.c **** A.item3 = 3;
99 .loc 1 28 0
100 0086 C7050800 movl $3, A+8
100 00000300
100 0000
29:complex_type.c **** A.item4 = 4;
101 .loc 1 29 0
102 0090 C7050C00 movl $4, A+12
102 00000400
102 0000
30:complex_type.c ****
31:complex_type.c **** printf("A.1 = %d, A.2 = %d, A.3 = %d, A.4 =
%d\n",
103 .loc 1 31 0
104 009a 83EC0C subl $12, %esp
105 009d FF350C00 pushl A+12
105 0000
106 00a3 FF350800 pushl A+8
106 0000
107 00a9 FF350400 pushl A+4
107 0000
108 00af FF350000 pushl A
108 0000
109 00b5 68400000 pushl $.LC1
109 00
110 .LCFI8:
GAS LISTING /tmp/ccQA6n9P.s page 4
111 00ba E8FCFFFF call printf
111 FF
112 00bf 83C420 addl $32, %esp
32:complex_type.c **** A.item1, A.item2, A.item3, A.item4);
33:complex_type.c ****
34:complex_type.c **** B = manipulate(A);
113 .loc 1 34 0
114 00c2 8D45E8 leal -24(%ebp), %eax
115 00c5 83EC0C subl $12, %esp
116 00c8 FF350C00 pushl A+12
116 0000
117 00ce FF350800 pushl A+8
117 0000
118 00d4 FF350400 pushl A+4
118 0000
119 00da FF350000 pushl A
119 0000
120 00e0 50 pushl %eax
121 00e1 E8FCFFFF call manipulate
121 FF
122 00e6 83C41C addl $28, %esp
35:complex_type.c **** printf("B.1 = %d, B.2 = %d, B.3 = %d, B.4 =
%d\n",
123 .loc 1 35 0
124 00e9 83EC0C subl $12, %esp
125 00ec FF75F4 pushl -12(%ebp)
126 00ef FF75F0 pushl -16(%ebp)
127 00f2 FF75EC pushl -20(%ebp)
128 00f5 FF75E8 pushl -24(%ebp)
129 00f8 68800000 pushl $.LC2
129 00
130 00fd E8FCFFFF call printf
130 FF
131 0102 83C420 addl $32, %esp
36:complex_type.c **** B.item1, B.item2, B.item3, B.item4);
37:complex_type.c ****
38:complex_type.c **** exit(0);
132 .loc 1 38 0
133 0105 83EC0C subl $12, %esp
134 0108 6A00 pushl $0
135 .LCFI9:
136 010a E8FCFFFF call exit
136 FF
39:complex_type.c **** }
137 .loc 1 39 0
138 .LBE2:
139 .LFE5:
141 .comm A,16,4
212 .Letext0:
2232 .ident "GCC: (GNU) 3.3.6"
GAS LISTING /tmp/ccQA6n9P.s page 5
DEFINED SYMBOLS
*ABS*:0000000000000000 complex_type.c
/tmp/ccQA6n9P.s:26 .text:0000000000000000 manipulate
/tmp/ccQA6n9P.s:82 .text:0000000000000062 main
*COM*:0000000000000010 A
UNDEFINED SYMBOLS
printf
exit
-------------------------
I have no idea why it's claiming 'printf' and 'exit' are undefined. ?:-/
Cheers!
Rich

Re: VON NEUMANN VS HARVARD
[....]

Yes you are right, it works on gcc. Some years back I tried it on quite a
different C compiler and it choked. Is this a case of a bad compiler or
is it something added in, lets say, the last 7 years.
BTW: Can this be done with an array?
--
--
snipped-for-privacy@rahul.net forging knowledge
snipped-for-privacy@rahul.net forging knowledge

Re: VON NEUMANN VS HARVARD

Dang! I don't know! How do you declare the function whose return value is
an array?
int[] foo(int[]); // ?
You have to hard-code the size, I think - or maybe union it onto a
structure? Then you'd still have to have a fixed size.
Probably not. Anybody want to try?
I'm gonna crosspost this to comp.lang.c , but set followups to
sci.electronics.design, because those c.l.c folks are a little touchy
about marginally off-topic posts and banter and stuff.
Thanks,
Rich

Re: VON NEUMANN VS HARVARD

you should use a pointer as the return value:
int* foo(int[]);

or you could pass the size as a parameter (emulating multiple return
values) that can be filled in by the function:
int* foo(int[] input, int *size);
and then before your return assign size:
*size = number_of_members_in_the_returned_array
return the_array_you_want_to_return
--
burton samograd kruhft .at. gmail
kruhft.blogspot.com www.myspace.com/kruhft metashell.blogspot.com
burton samograd kruhft .at. gmail
kruhft.blogspot.com www.myspace.com/kruhft metashell.blogspot.com

Re: VON NEUMANN VS HARVARD
[...]

No, not always. That capability, along with structure assignment, was
added not long after K&R1 (Kernighan & Ritchie, _The C Programming
Language_, 1st Edition, which was the de facto language definition
before the 1989 ANSI standard was published).
Though I suppose in this business a few decades or so is close enough
to "always".
--
Keith Thompson (The_Other_Keith) snipped-for-privacy@mib.org <http://www.ghoti.net/~kst
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst
Keith Thompson (The_Other_Keith) snipped-for-privacy@mib.org <http://www.ghoti.net/~kst
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst
We've slightly trimmed the long signature. Click to see the full one.

Re: VON NEUMANN VS HARVARD
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Robert Gamble wrote:

Sorry, but you are mistaken.
"There are a number of restrictions on C structures. The essential rules are
that the only operations that you can perform on a structure are take its
address with &, and access one of its memebers. This implies that structures
may not be assigned to or copied as a unit, and that they can not be passed
===============
to or returned from functions."
=======================
The C Programming Language
Brian W. Kernighan * Dennis M. Ritchie
Copyright (c) 1978 by Bell Telephone Laboratories, Incorporated
It has been possible to pass and return _pointers to structures_ in C, but
only recent standards (i.e. 89 and after) permitted passing and returning
actual structures.
[snip]
HTH
- --
Lew Pitcher
Master Codewright & JOAT-in-training | GPG public key available on request
Registered Linux User #112576 (http://counter.li.org /)
Slackware - Because I know what I'm doing.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.2 (GNU/Linux)
iD8DBQFEPu5SagVFX4UWr64RAnGiAKCdgETkkIeNzxP5Tv9eRMVoNMNDrACfZsgX
4mJdM+L09jlZnyitjMNHahw=
=ZtRY
-----END PGP SIGNATURE-----

Re: VON NEUMANN VS HARVARD

No, the ability to pass and return structures was added
into Unix Version 7 C. Along with the enumeration type.
_Recent Changes to C_,
November 15, 1978,
Page 277, Unix Programmers Manul, V.2
1979, 1983, Bell Telephone Laboratories
Holt Reinhart and Wilson
There was a warning that the PDP-11 version didn't handle
reentrancy within an interrupt properly, though.
Mark Zenier snipped-for-privacy@eskimo.com
Googleproofaddress(account:mzenier provider:eskimo domain:com)

Re: VON NEUMANN VS HARVARD

That compiler was broken. The C89 standard allowed passing and returning
structures.

You can't. Not directly.

Close. Just declare a structure with the array as an element ant return
that. Just be aware that it means the array is getting copied around
which can be rather inefficient.
struct arr_ret {
int a[5];
};
struct arr_ret foo(int*);
Generally I would pass a pointer to the first element of the return
array instead, just like memcpy, strcpy etc.

You're question is about C and that is fine here and we don't mind a bit
of banter so I've re-instated the cross-post. Just remove the cross-post
if the thread drifts off C on to other things.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk /
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk /
We've slightly trimmed the long signature. Click to see the full one.

Re: VON NEUMANN VS HARVARD
[....]

But if you do that, you loose the ability to check for overruns. The
point was that using pointers makes checking very hard to implement. If
you are only returning a 3 or 4 element array, the cost of the extra
overhead may be worth it.
It was part of my explaination[1] of why the C language is so horrid.
[1] troll
I have to admit it isn't as bad as C++ or Intercal.
--
--
snipped-for-privacy@rahul.net forging knowledge
snipped-for-privacy@rahul.net forging knowledge

Re: VON NEUMANN VS HARVARD

OK, I can accept that.

In some respects C is a horrid language and there are a number of things
I wish were different.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk /
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk /
We've slightly trimmed the long signature. Click to see the full one.

Re: VON NEUMANN VS HARVARD

You seem to miss the point that C CAN IN FACT pass and return a complex
data type. You don't need to use a pointer though lots of C programs
do. If you want you can pass the struct itself:
struct foo {
int x;
int y;
}
struct foo doubleFoo(struct foo f) {
f.x = f.x * 2;
f.y = f.y * 2;
return f;
}
int main(void) {
struct foo bar;
bar.x = 1;
bar.y = 1;
bar = doubleFoo(bar);
return 0;
}
Site Timeline
- » LCD module on sale
- — Next thread in » Electronics Design
-
- » Portable Wall Sockets
- — Previous thread in » Electronics Design
-
- » tiny table saw
- — Newest thread in » Electronics Design
-
- » OT: Why the death penalty is still needed
- — Last Updated thread in » Electronics Design
-
- » Sistema di sviluppo Freescale serie Tower
- — The site's Newest Thread. Posted in » Electronics Hobby (Italian)
-