So test your theory and vote Democrat.
...Jim Thompson
So test your theory and vote Democrat.
...Jim Thompson
A couple of years ago, I was going to enter one of the Circuit Cellar design contests. The MCU looked really interesting, so I worked out a flow char of what I wanted, and then started looking into the code.
First, I looked at some of the sample code. Couldn't make heads or tails of it! I could see that they were basically setting bits here and there, but didn't know what bits they were setting! So, started searching through the files on the various defined variables, and found out that the pile was about 4 layers, with the defines in the actual code mapped to definition in a layer of summaries, which mapped to a layer of ports, which mapped ot what was really a top level elegant definition of every single port and bit in the processor! Now, if they had just used those defines directly, it would have been simplicity itself to understand the code, but I guess they wanted to be able to 'move' a function from say TIMER A to TIMER B just by changing a mid-level define.
Finally, after about 3 weeks, I gave up on the software, and the contest!
Charlie
Just for S&G, I just now dashed this off:
-------------------------------------------------- /* constants.c */ /* just a little quickie to see what gcc does with a 'const' keyword. */ #include
const int c = 4;
int main(int argc, char **argv) { printf("c = %d\\n", c); }
--------------------------------------------------
and it compiled and ran just fine on gcc 3.3.6 .
So that takes care of a _lot_ of the potential #define problems. (the "const" keyword - it's new since K&R, AFAIK.)
A macro shouldn't be more than one line, and self-explanatory. If you go to two or more lines, use a function - some compilers are smart enough to compile little functions in-line. :-)
Cheers! Rich
On Tue, 12 Sep 2006 09:52:28 -0700, Tim Wescott wrote: ...
Hear, Hear!!
Cheers! Rich
As I remember, one of the "features" of the pascal-style call/return was that they used the "RET n" instruction, which would increment (or decrement, whatever - essentially un-push but lose the data) the stack pointer by n, and _then_ return. So it was the programmer's responsibility to see to it that he/she pushed exactly the right number of parameters, every call. In C-style, it's the responsibility of the calling routine to pop the variables back off the stack (usually by restoring it from the base pointer, where it was stored before the call, I think.)
C style makes it possible to pass a variable number of parameters, a la printf().
Cheers! Rich
Hi Rich,
[deleted]I agree, in probably 90+% of the cases I've seen, a proper function or a "const" variable could take the place of #define.
The primarily time they can't is when you are dealing with a C compiler and not a C++ one. (Although I believe "const" shows up in something like C99 that is widely ignored.)
---Joel
const is in ANSI C / ISO C / C89 so should be supported by pretty much everything.
The 'inline' function specifier is very nice for replacing macros. That is from C99.
Tim
I heard that the Burroughs machines never had an assembler, and that the first Algol compiler was written in Algol. It was hand-compiled by two guys who "executed" it by hand, as the first bootstrap.
John
Ahem. The industry *needed*, *wanted*, and *chose* a monopolist. They might have chosen better, and their choice should have acted better (more altruistically), but that's a hypothetical argument. People need to interchange documents and skills, and the open source movement must necessarily be *always* too late to become the dominant player in such games... for better or worse, mostly worse :-). It's simply less efficient, slower, and the results more problematic, to create standards that a community agrees to implement than it is for a self-interested party in a competitive situation to create a single solution to a given problem.
The only way of evening things out a little would be to legislate that every piece of data created and owned by a user of proprietry software must be in a format that's documented to the level that a third party could produce a program that performs the same functions with that data possible with the proprietry software. Call this the "principle of data transparency". In this respect, hackers actually perform a useful service to the community when they reverse-engineer data storage formats, for whatever nefarious purposes.
Clifford Heath.
My embedded systems never terminate; if they terminated, they's stop functioning, and that's equivalent to "it broke."
My software state machines resemble classic hardware state machines; they do sometimes execute blocks in stately progression, they sometimes execute the same block 219 times in succession, and they do sometimes jump around all over the place. But each block does something, has a maximum allowed execution time, and exits when it's done, usually within a millisecond and often a lot less.
And the dispatcher is usually within a periodic ISR, which does...
save stuff run stuff that's got to be done every time run a block of a state machine unsave stuff rti
and, of course, each state machine block can change which block will be run next pass through. Works like a cookoo clock. I time block executions with a scope and enter them in the source as comments.
John
If I haven't accidentally mixed up the attributions,
"They have been at a great feast of languages, and stolen the scraps."
-- Shakespeare, Love's Labour's Lost.
A 'const' qualifier in C89, C90, C99 does not define a constant. It specifies a read-only variable. Thus you cannot use const in the following sense:
const int x = 4; int a[x];
that requires a "#define x 4" statement.
In article , Steve at fivetrees wrote: [....]
Yes, this was another level of horror I built into the code with no GOTOs.
Often when I write an example of that method, I also shuffle the order of the statements just to make it extra unreadable. This would be a 3rd level of horror, just in case those reading it would otherwise keep lunch down.
[...]I sometimes do multitasking with a context swapping method. I have a routine called something like "OtherTask" that pushes everything, swaps stacks, pops everything and returns. You can bobble back and forth between two tasks that look like linear programs that way.
You can even create your own fixed priority interrupt based multitasker without much work if you only need 2 or three tasks.
Not so. Historically, in the days of CP/M, many standards were set by the open source movement, although it wasn't called that then. The LBR format, the Xmodem and Ymodem transmission standards, the compression standards, including crunch and sqz, were all developed in the open and had many hands involved. There are many other examples, possibly not quite as pervasive. The LBR format was the ancestor of ARC, which begat ZIP, in the PC world. X and Y modem begat Zmodem, which remains an important standard.
In article , John Larkin wrote: [....]
For some meanings of the word terminate quite a few embedded programs terminate. The basically restart from the beginning.
You can also do this: Modified code:
run a block of state machine B
If the two state machine blocks take very small amounts of time to do, this can make for code that is easier to work on if the number of states in the two machines are very different.
Yup. You can also give chain A priority, in the sense that "if an A block is runnable, execute it and exit; if not, run a B block." This is sort of a zen RTOS.
There's also the "rotary dispatcher." State-block list A might have, say, 12 entries that are executed in rotation. But one of those 12 blocks in turn does a rotary call to a second B list of blocks. The second-list blocks then get run at a much lower rate than the A-list ones. The A list may be scanning analogs, driving a VF display, protecting fets, whatever. B list may be checking pushbuttons, reading slow SPI temperature sensors, or managing startup/shutdown modes. I've done this 3 levels deep, 2 levels wide, all diagrammed on a D-size sheet of vellum.
You can also make a list of, say, 64 dispatch pointers...
BlockP BlockQ BlockP BlockR BlockP...
or something like that. The more often a block pointer appears in the list, the more compute time that operation gets. P gets run every other IRQ, but R might run only once every 64.
John
Yawn. I was there twenty-five years ago also, but the world was different then. A competent programmer with a few weeks available and the right information (techniques) could have written a Wordstar clone, a Kermit clone, a ZIP clone, etc. I *know* that, because I did all three.
OTOH, try getting one person to write a modern wordprocessor in six weeks... As soon as you need dozens of people to do something, as soon as something cannot be done by a dedicated individual, you have a qualitative shift. I wish you were right, but alas...
Clifford Heath.
Nonono. I did say "the process", not "the program".
Steve
You can use an enumeration instead, can't you?
enum { x=1024, y=2048, z=129, /* other "constants" here */ };
int a[x]; int b[y]; int c[z];
etc.
A friend of mine used to use a "gotoavoidanceflag" in RTL/2. The purists didn't like that either.
Have something to add? Share your thoughts — no account required.
Ask the community — no account required