From: Grant Edwards on
On 2010-06-02, David Brown <david.brown(a)hesbynett.removethisbit.no> wrote:
> D Yuniskis wrote:
>> Hi Tim,
>>
>> Tim Wescott wrote:
>>> Exception handling in object-oriented programming is specifically
>>> designed to address the problems in C++ that C's "goto" and long
>>> branch (long goto? I can't remember what it's called) solve in C.
>>
>> setjmp()/longjmp()?
>
> People who are allergic to "goto" in C should run screaming at the sight
> of these functions!

:)

Using setjmp()/longjmp() to handle exceptions is far harder to
understand (and in my experience causes many more bugs) than using
goto for the same thing.

> There are times when "goto" is the best way to structure your code -
> I've used it a few times. You have to be careful with it, as it's easy
> to write spaghetti code and lose track of things like variable
> initialisations (C++ is fussier about when you are allowed to use it).
> But setjmp() and longjmp() are far worse - if you think you need them,
> you are almost certainly wrong and should re-structure your code. (If
> you /know/ you need them, it's a different matter - few rules in C
> programming are absolute.)

Don't use scanf() is pretty close to one of the absolute rules. ;)

--
Grant


From: Royston Vasey on

"D Yuniskis" <not.going.to.be(a)seen.com> wrote in message
news:hu5tr8$qpk$1(a)speranza.aioe.org...
> Hi Royston,
>
> Royston Vasey wrote:
>> I've got a very basic question guys, I'm teaching myself C using
>> Microchip's C18 compiler.
>
> Great!
>
>> I've got my main loop running, looking for certain conditions to occur,
>> receiving a serial command & processing it.
>>
>> I need to monitor a few things for a time out condition, to do this I'm
>> pre-loading Timer1 with the required values and when the timer overflows
>> it jumps to the relevant interrupt.
>
> What are you timing? I.e., are you trying to prevent the
> code from waiting for a received character indefinitely?
> Or, trying to abort a system call after a certain time limit
> is exceeded? etc.
>
>> All the above works fine.
>>
>> When the Timer1 interrupt fires what is the easiest/best/correct way to
>> execute a block of "reset" code and then recommence execution at a
>> _particular_ place in the main() loop?
>
> <frown> You (typically) can't just jump around your code
> "willy nilly" -- unless you really know what's going on under
> the hood (doubtful if you're just learning).
>
> E.g., when the IRQ is signalled, *something* was being done
> at that time. That "something" has to be considered when
> you decide to *abandon* it (by jumping to a *particular*
> place in the main() loop).
>
> If, for example, the code was busy *deep* in some nested
> function call -- lots of cruft on the stack -- and you
> just "jumped" to someplace else to "resume execution",
> then you have all that cruft still sitting on the stack
> with nothing to unroll it. (what happens if the *next*
> interrupt does the exact same thing? and the one after
> that? i.e., you eventually "blow the stack" because you've
> never cleaned its previous contents off of it)
>
> Even if you were lucky enough to be able to perform the
> jump without consequence, you can't jump to any arbitrary
> point in "main()" -- because you don't know what the
> prerequisites for that part of main happen to be.
> Consider, what would you expect the code to do if you jumped
> into the middle of a "for" loop?
>
> If you are building an application that relies on a simple
> while loop for it's structure, then you have to poll every
> "event" of interest in that loop and "dispatch" accordingly
> *from* that loop. Your interrupt has to be "invisible"
> to the application (in terms of how it *immediately*
> affects program flow).
>
> If you want to implement a simple timeout, try something like:
> - set a (volatile) flag (*bit*!) someplace "common"
> - have the ISR *clear* that flag when it occurs
> - have whatever "service" you are trying to "time"
> poll that flag along with whatever else it is supposed
> to do; if it sees the flag get cleared "magically", the
> service returns an error (TIMEOUT) instead of success
>
> So, if you wanted to put a timeout on how long you would
> wait for a character to be received:
>
> result
> receive_character(char *character, boolean *flag) {
> while (*flag == SET) {
> if (check_UART_for_character() == TRUE) {
> *character = get_UART_character();
> return SUCCESS;
> }
> return FAILURE;
> }
>
> I.e., as long as the flag is still *set*, keep checking the
> UART to see if a character is available. If so, return the
> character *and* indicate "SUCCESS".
>
> However, once the flag is NOT "SET", stop checking the
> UART and just return a FAILURE (TIMEOUT) indication.
>
> Your main() then does something like:
>
> // setup hardware
> boolean waiting;
>
> ...
> while (FOREVER) {
> char character;
> ...
> start_timer(&waiting, time_limit);
> if (receive_character(&character, &waiting) == SUCCESS)
> // do something with "character"
> else
> // character didn't show up in the prescribed time limit
> ...
> }
>
> void
> start_timer(boolean *flag, timeout_t timeout) {
> *flag = SET;
> set_hardware_timer(timeout);
> }
>
> and your ISR does:
>
> void
> ISR(void) {
> // diddle with the hardware
> waiting = ~SET;
> }
>
> (I've not proofed this for typos :< )
>
>> Using assembly I would have used "goto" to steer execution where I wanted
>> it, but how is it approached in C?



Whew! Thanks for all of the replies guys - the time you put into helping me
out really is appreciated.

I think I'll go with Don's suggestion - in hindsight it's a little obvious
that this is what I should do. Thanks also Tim, Joseph, Hamilton.

I once read somewhere that if you can write in assembler then C should be
easy - either I misunderstood or whoever said it was WRONG! :)

Now to implement it!

cheers
Royston


From: D Yuniskis on
Hi Royston,

Royston Vasey wrote:
> I once read somewhere that if you can write in assembler then C should be
> easy - either I misunderstood or whoever said it was WRONG! :)

The problem you are having is that C hides a bit more of the
hardware from you that ASM would.

E.g., in ASM, you would be more aware of what's on the stack, etc.
You wouldn't do something like:

MAIN:
...
CALL FOO
...


FOO: CALL BAR
...


BAR: CALL BAZ
...



BAZ: JUMP MAIN

(because you'll munge the stack!)

> Now to implement it!
From: Albert van der Horst on
In article <-Nqdnb42dZ740JvRnZ2dnUVZ_tydnZ2d(a)westnet.com.au>,
Royston Vasey <royston(a)vasey.com> wrote:
>I've got a very basic question guys, I'm teaching myself C using Microchip's
>C18 compiler.

Although this is c.l.e I would recommend using Turbo C 2.0 to learn
C. If you can get it. No distraction from the language itself.

>
>Thanks.

Groetjes Albert

--
--
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert(a)spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

From: Royston Vasey on

"Albert van der Horst" <albert(a)spenarnc.xs4all.nl> wrote in message
news:l3gfns.fy5(a)spenarnc.xs4all.nl...
> In article <-Nqdnb42dZ740JvRnZ2dnUVZ_tydnZ2d(a)westnet.com.au>,
> Royston Vasey <royston(a)vasey.com> wrote:
>>I've got a very basic question guys, I'm teaching myself C using
>>Microchip's
>>C18 compiler.
>
> Although this is c.l.e I would recommend using Turbo C 2.0 to learn
> C. If you can get it. No distraction from the language itself.
>
>>
>>Thanks.
>
> Groetjes Albert
>
> --
> --
> Albert van der Horst, UTRECHT,THE NETHERLANDS
> Economic growth -- being exponential -- ultimately falters.
> albert(a)spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst
>

Thanks Albert, but I'm using C18 as my objective is to created an embedded
device and the direct route suits me best.


First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4 5 6 7 8
Prev: ready to run 32bit controller
Next: ARM7