Reply by Sander Vesik June 28, 20042004-06-28
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. >
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