Prev: ready to run 32bit controller
Next: ARM7
From: Grant Edwards on 2 Jun 2010 20:45 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 3 Jun 2010 02:07 "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 3 Jun 2010 02:48 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 3 Jun 2010 16:02 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 4 Jun 2010 00:08
"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. |