[C.CC USERS] placed variables?
Matt Jadud
jadudm at gmail.com
Mon Aug 9 17:20:22 BST 2010
Hi Patrick,
On Mon, Aug 9, 2010 at 11:20 AM, Patrick J.G.C. Weemeeuw
<pweemeeuw at telenet.be> wrote:
> After playing a bit with occam on my arduino -- I like it very much -- I want to keep track of time for my measurements.
>
> I thought about something along the following lines:
>
> -----------------------------------------
>
> #INCLUDE "plumbing.module"
>
> VAL INT clockresolution IS #03E8: -- one tick every 1000 ms
>
> PROC timekeeper ()
> PLACED INT64 now: -- which address?
> TIMER tim:
> INT t:
> SEQ
> WHILE TRUE
> SEQ
> tim ? t
> -- maintain 'now' here, based on t and t's previous value
> serial.write.string(TX0, "time: ")
> serial.write.int(TX0, now)
> serial.write.newline(TX0)
> delay(clockresolution)
> :
Good thinking. I'll try and get some pointers online to more resources
shortly, which will help with timer exploration. This will output the
time every now and then.
Another way to do this is the following:
TIMER tim:
INT start, end:
SEQ
tim ? start
.. do stuff ..
tim ? end
.. show difference between start and end (time is in ms)...
You could do that directly in your code, or you could wrap it up in a proc:
PROC timkeeper (CHAN SIGNAL gate?, CHAN INT diff!)
TIMER tim:
INT start, end:
WHILE TRUE
SEQ
gate ? SIGNAL
tim ? start
gate ? SIGNAL
tim ? end
diff ! (end - start)
:
Admittedly, you'll get some comms/scheduling overhead in this, which
may be undesirable. The overhead would be because timer reads are
scheduling points, so things can happen in-between all of those
communications. This is where the *soft* realtime nature of our
implementation can bite you if you're not thinking about it. If you
needed to get the current time without descheduling for performance
reasons, we could talk about that.)
Not knowing more about what you're trying to time, that is about all I
can say there.
> I have 2 questions:
> - are placed variables supported in concurrency/plumbing (I'm still confusing the names)?
Yes. In fact, if you look in the platform-specific code, you'll see
where we place the ports array. We have code that looks like this:
http://projects.cs.kent.ac.uk/projects/kroc/trac/browser/kroc/trunk/tvm/arduino/occam/include/arch/common/pin.module#L37
PLACED [MAX.PORT]BYTE ports 0:
#PRAGMA DEFINED ports
I cannot remember, but it might be that we can only place arrays.
Regardless, the code above places an array of bytes of length 512
(MAX.PORT is defined elsewhere) starting at memory address zero. By
placing the variable, we are not manipulating memory... but at the
point that we write to it, we *are*. On the Arduino, we do this to
access the registers of the AVR natively. (The #PRAGMA tells the
compiler not to yell at us about the array being undefined; that's a
dangerous thing to do in occam-pi, but when you're doing direct
hardware programming, it's obvious that we sometimes have to get
directly at registers.)
At this point, we can do things like the following:
ports[r.port] := (ports[r.port] /\ (~BV (bit))) \/ ((BYTE state) << bit)
where "r.port", "state", and "bit" are variables that were passed into
the PROC.
ports[PORTB]
uses the symbolic constant PORTB (pulled directly from the C header
file) to access into the correct location in memory on the AVR. When
we are programming "natively" against the AVR, the code looks very,
very similar to C... except we do it entirely by referencing into the
PLACEd array.
Does that make sense? The constant files for the various chips are in
the arch/ directory.
> - what address should I use in the variable declaration?
Well, that's up to you. I would not casually do direct memory
manipulation. If what you're trying to do is manipulate AVR registers,
then look at any of our code in arch/ for examples. If you're trying
to pass values from one PROC to another, then use channels. There are
no global variables in occam-pi, and if you try and force the issue
with a placed value, you might:
1. Put it directly into an AVR register, causing a crash.
2. Put it directly into memory statically allocated to the VM, causing a crash.
3. Put it directly into memory statically allocated to your program,
causing a crash.
4. Find a bit of unused RAM, and get lucky.
:)
Up to you. Feel free to ask more questions/say more about what you're
trying to achieve if that didn't help.
(I'll be getting up to speed on fixing some things and getting
resources on-line -- my day job of being a professor is kicking into
gear at this point...)
Cheers,
Matt
More information about the users
mailing list