> Hans-Bernhard Broeker wrote:
> >
> > You're not getting my point. Which is that the C standard only
> > demands that a byte is directly addressable, but not that everything
> > directly addressable by the hardware must be a byte (by C's definition
> > of the term) of its own. Otherwise, on 8051s a byte would have to be
> > 1 bit wide, because they can address single bits.
>
> You're right, I'm not getting your point. If a byte must be directly
> addressable and be able to hold a character, then it would have to be
> either 24 or 32 bits on this hardware since 19 bits is not directly
> addressable.
>
umm... yes it is. the "gotcha" is simply that any larger datatype needs
to be at least 38 bits long (if such exists - they might not).
--
Sander
+++ Out of cheese error +++
Reply by Bernhard Holzmayer●June 15, 20042004-06-15
Hi Alex,
here's how I would handle this issue ...
Alex Sanks wrote:
> ...
> I'm working with some firmware drivers which are intended to be as
> portable as possible.
Being aware that complete portability across very different
platforms will be not achievable, I'd sstart with declaring
different environment with #define PLATFORM_1 etc.
> Data
Bc. data types might differ (as you indicate) whereever they're
received/transmitted/transformed, use 'typedef' or similar methods
to abstract from machine/compiler specific types wherever possible.
Your u8, u32 types are a good start.
> moves
Data doesn't move by itself. Instead, you have to move data.
How, might differ depending on the peripheral (USB controller,...)
and/or on the machine/platform/compiler.
Thus, again you might use #define/#ifdef to handle data movements.
This means, install generic handler routines to move data, which do
all the machine/platform/compiler/periphery dependent stuff, and
which provide a generic interface.
Then you can keep the rest of the software (almost ?) portable.
If you want some fairly good examples of how to do such things,
you might want to read the source code files of the Linux OS.
Especially of interest for your work might be the book "Linux device
drivers" ,Alessandro Rubini, which gives a lot of good hints.
> thru a switchable 8- or 16-bit
> data bus chip (a USB device controller specifically).
> Performance is critical so 16-bit is pretty much necessary.
I guess you mean Performance='fast execution'.
So, you might want to do things in compile time whereever possible.
One example to do a thing in compile time instead of runtime, is
this:
u16 x;
u8 y;
x=1234;
y = x & 0xff; /* this is the runtime approach */
u8 y;
union {
u16 x16;
u8 x8_1;
u8 x8_2;
} ux;
ux.x16=1234;
y=ux.x8_2; /* this is the compile time approach */
Though this approach is highly machine/compiler dependent,
it may save you lot of time, thus giving you performance gain.
Probably, you'll have to implement such a thing individually for
every new environment.
Which means, that the scope of such critical things should be as
small as possible.
> Following that example,
> let's look at the USB mass storage class. You get commands from
> the host in 31 octet
I count only 30 ...?!
> command wrappers that look like this (endian
> issues aside...):
>
> typedef struct
> {
> u32 Signature;
> u32 Tag;
> u32 TransferLength;
> u8 Flags;
> u8 Lun;
> u8 CommandLength;
> u8 Command[15];
> } Cbw;
>
> If I have 8 bit data types that's easy enough to get and deal
> with. But right now I'm working with a TMS320C55x variant with
> nothing
> smaller than 16-bit data types.
Approach depends on where you need your performance and where the
conversions are cheapest. One might be to define a 16bit type which
holds two octets:
typedef union {
u16 the16wide;
u16 the8wideH:8;
u16 the8wideL:8;
} my16;
.... my32;
Based on this you could define your structure with
typedef struct
{
my32 Signature;
my16 Tag01;
my16 Tag23;
...
} Cbw;
For convenience, you might define:
#define Signature0 Signature.the8wide0
...
#define Tag0 Tag01.the8wideH
#define Tag1 Tag01.the8wideL
Then you can access the data as usual with Cbw.Tag1 or with
Cbw.Signature or however you want.
>
> Ugly.
Certainly, that's ugly.
Since I did some device drivers which had to be "a little bit"
portable, I'd say that you'll not be able to avoid such ugly
things. With a little effort, you can write things so that they are
readable without chance to misunderstand what is meant.
This would be a great thing and certainly highly appreciated by
those people who have to modify your code later.
I'd try to hide all the ugly things in extra files and keep them as
small as possible. Try to keep the rest neat, instead.
> I'd really like to avoid that...
You're free to like it or dislike it. That's life that you don't
always get what you like...
> ...
> I don't care if everything's stored locally inefficiently.
If so, why not just define a
typedef u16 BYTE;
define the structure as you wrote andignore the unused bytes.
However, to avoid that some other function works with corrupted
data, or corrupts them, I'd write access functions which are the
only to work on the structure.
Hide the data structure in a .c-file together with the manipulator
functions, and export in the .h-file not the structure, but the
manipulator functions together with an abstract, generic container
type. This could look like:
---------- file.h ------------
typedef unsigned short u16;
typedef unsigned long u32;
typedef struct {
u32 signature;
u16 tag;
....
} genericCBW;
int read_data(genericCBW * returnsDataHere);
int write_data(genericCBW * needsDataHere);
---------------------------
--------- file.c ------------
#define PLATFORM
all the ugly stuff you can't avoid...
all your conversions necessary, all the real read/write
accesses and the definitions for all the real data storage elements.
(your real Cbw structures)
int read_data(genericCBW * returnsDataHere)
{
returnsDataHere->signature = functionwhichknowshowtogetSignature();
...
}
int write_data(genericCBW * needsDataHere)
{
functionwhichknowshowtowriteSignature(needsDataHere->signature);
}
---------------------------
>
> I'm making progress getting things to work, but it's getting ugly
> so I was curious how people deal with this in real life.
>
> Thanks for whatever guidance you can provide,
> alex
Bernhard
Reply by Anton Erasmus●June 14, 20042004-06-14
On Mon, 14 Jun 2004 11:00:35 -0400, Jim Thomas <jthomas@bittware.com>
wrote:
>Anton Erasmus wrote:
>> One portable way I have seen to force C to use a specific size is the
>> following:
>>
>> typedef struct {unsigned data:8;} BYTE;
>>
>> The only problem is that if you define a variable as
>>
>> BYTE foo;
>>
>> you have to use it with following syntax
>>
>> foo.data=20;
>
>Unfortunately, that's not the only problem. The C standard does not
>dictate the order of bits in a bit field. The compiler is at liberty to
>put the first N bits in the ls-bits or the ms-bits, so this:
>
>typedef struct
>{
> byte_a : 8;
> byte_b : 8;
>}
>
>Can have byte_a in the upper 8 bits or in the lower 8-bits. If you're
>exchanging this data between two machines that use two different
>compilers, you have to make sure they speak the same bit field lingo, or
>you have to jump through hoops to re-define them based on how they get
>packed. I think "portable" and "jump through hoops" could be considered
>mutually exclusive.
Getting data to have the same memory layout in different compilers and
on different architectures are a total different ballgame. The method
I proposed only handles the size issue. To handle the actual memory
layout one would have to use #pragmas or some other non-portable
directives to do this. I do agree that this is inherantly
non-portable.
Regards
Anton Erasmus
Reply by Jim Thomas●June 14, 20042004-06-14
Anton Erasmus wrote:
> One portable way I have seen to force C to use a specific size is the
> following:
>
> typedef struct {unsigned data:8;} BYTE;
>
> The only problem is that if you define a variable as
>
> BYTE foo;
>
> you have to use it with following syntax
>
> foo.data=20;
Unfortunately, that's not the only problem. The C standard does not
dictate the order of bits in a bit field. The compiler is at liberty to
put the first N bits in the ls-bits or the ms-bits, so this:
typedef struct
{
byte_a : 8;
byte_b : 8;
}
Can have byte_a in the upper 8 bits or in the lower 8-bits. If you're
exchanging this data between two machines that use two different
compilers, you have to make sure they speak the same bit field lingo, or
you have to jump through hoops to re-define them based on how they get
packed. I think "portable" and "jump through hoops" could be considered
mutually exclusive.
--
Jim Thomas Principal Applications Engineer Bittware, Inc
jthomas@bittware.com http://www.bittware.com (703) 779-7770
A pessimist is an optimist with experience
Reply by Hans-Bernhard Broeker●June 14, 20042004-06-14
rickman <spamgoeshere4@yahoo.com> wrote:
> Hans-Bernhard Broeker wrote:
> >
> > You're not getting my point. Which is that the C standard only
> > demands that a byte is directly addressable, but not that everything
> > directly addressable by the hardware must be a byte (by C's definition
> > of the term) of its own. Otherwise, on 8051s a byte would have to be
> > 1 bit wide, because they can address single bits.
> You're right, I'm not getting your point. If a byte must be directly
> addressable and be able to hold a character, then it would have to be
> either 24 or 32 bits on this hardware since 19 bits is not directly
> addressable.
I've expanded on this before, so I'll just summarize: if you declare 5
out of 24 (or 13 out of 32) bits as non-existant or unusable, then a C
byte can be 19 bits large, even if the hardware addresses multiples of
8 bits. A C compiler is allowed to abstract from the actual hardware.
Even in utterly foolish ways.
--
Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.
Reply by Thad Smith●June 14, 20042004-06-14
rickman wrote:
> Hans-Bernhard Broeker wrote:
>
>>You're not getting my point. Which is that the C standard only
>>demands that a byte is directly addressable, but not that everything
>>directly addressable by the hardware must be a byte (by C's definition
>>of the term) of its own. Otherwise, on 8051s a byte would have to be
>>1 bit wide, because they can address single bits.
>
> You're right, I'm not getting your point. If a byte must be directly
> addressable and be able to hold a character, then it would have to be
> either 24 or 32 bits on this hardware since 19 bits is not directly
> addressable.
Yes. One of the other issues is that memory is measured in contiguous
bytes and that an unsigned char has no unused bits. 19-bit character
codes in 24-bit bytes would be analogous to 7-bit ASCII stored in 8-bit
bytes.
Thad
Reply by William Meyer●June 13, 20042004-06-13
oN 11-Jun-04, Alan Balmer said:
> I think it was a Spanish "dollar", though. Pieces of eight.
Yes, you're right.
--
Bill
Posted with XanaNews Version 1.16.3.1
Reply by rickman●June 13, 20042004-06-13
Jeff Fox wrote:
>
> Guy Macon <http://www.guymacon.com> wrote in message news:<10ck1aasnts30f6@corp.supernews.com>...
> >
> > Following ?bit?, ?byte? and ?nybble? there have been quite a
> > few analogical attempts to construct unambiguous terms for
> > bit blocks of other sizes. All of these are strictly jargon,
> > not techspeak, and not very common jargon at that (most
> > hackers would recognize them in context but not use them
> > spontaneously). We collect them here for reference together
> > with the ambiguous techspeak terms ?word?, ?half-word?,
> > ?double word?, and ?quad? or quad word; some (indicated)
> > have substantial information separate entries.
> >
> > 2 bits: crumb, quad, quarter, tayste, tydbit, morsel
> >
> > 4 bits: nybble
> >
> > 5 bits: nickle
>
> Does it matter if they are made of wood?
>
> > 10 bits: deckle
>
> 12 bits? dozzyl? foot?
14 bits: fortbit
> > 16 bits: playte, chawmp (on a 32-bit machine), word (on a 16-bit machine),
> > half-word (on a 32-bit machine).
> >
> > 18 bits: chawmp (on a 36-bit machine), half-word (on a 36-bit machine)
>
> What is it called on an 18-bit machine?
>
> 20 bits? icosle
> 21 bits? majoritle
> 24 bits? bidozzyl, day
31 bits: month
> > 32 bits: dynner, gawble (on a 32-bit machine), word (on a 32-bit machine),
> > longword (on a 16-bit machine).
> >
> > 36 bits: word (on a 36-bit machine), yard
> > 48 bits: gawble (under circumstances that remain obscure)
52 bits: deck
> > 64 bits: double word (on a 32-bit machine) quad (on a 16-bit machine)
76 bits: trombone
80 bits: PhileasFogg
> > 128 bits: quad (on a 32-bit machine)
144 bits: dergrossbit
365 bits: year
366 bits: leapyear
--
Rick "rickman" Collins
rick.collins@XYarius.com
Ignore the reply address. To email me use the above address with the XY
removed.
Arius - A Signal Processing Solutions Company
Specializing in DSP and FPGA design URL http://www.arius.com
4 King Ave 301-682-7772 Voice
Frederick, MD 21701-3110 301-682-7666 FAX
Reply by rickman●June 13, 20042004-06-13
Hans-Bernhard Broeker wrote:
>
> You're not getting my point. Which is that the C standard only
> demands that a byte is directly addressable, but not that everything
> directly addressable by the hardware must be a byte (by C's definition
> of the term) of its own. Otherwise, on 8051s a byte would have to be
> 1 bit wide, because they can address single bits.
You're right, I'm not getting your point. If a byte must be directly
addressable and be able to hold a character, then it would have to be
either 24 or 32 bits on this hardware since 19 bits is not directly
addressable.
--
Rick "rickman" Collins
rick.collins@XYarius.com
Ignore the reply address. To email me use the above address with the XY
removed.
Arius - A Signal Processing Solutions Company
Specializing in DSP and FPGA design URL http://www.arius.com
4 King Ave 301-682-7772 Voice
Frederick, MD 21701-3110 301-682-7666 FAX
Reply by Paul Keinanen●June 13, 20042004-06-13
On 10 Jun 2004 16:59:49 -0700, usenet1@sanks.net (Alex Sanks) wrote:
>
>I'm working with some firmware drivers which are intended to be as
>portable as possible. Data moves thru a switchable 8- or 16-bit data
>bus chip (a USB device controller specifically). Performance is
>critical so 16-bit is pretty much necessary. Following that example,
>let's look at the USB mass storage class. You get commands from the
>host in 31 octet command wrappers that look like this (endian issues
>aside...):
I do not see much point in this discussion, unless you also consider
the endian issues if you really want the code to be as portable as
possible.
If the endianess of the message and your hardware does not match, you
sooner or later have to isolate the bytes and rearrange them, so why
not do it immediately when assembling or disassembling the data frame.
Postponing the endianess handling to a later stage only makes sense if
the hardware contains a nice byte swap instruction (or an 8 bit rotate
instruction on a 16 bit register), to be included with an in-line
assembly statement, but this is not very portable :-).
Paul