Arduino Due Timer Syntax question

Go To Last Post
21 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am currently trying to learn how to program the Arduino Due timer in Atmel Studio 7 using a Jtag connector from an ICE.

 

I have got a basic light flasher working but I am confused by some of the syntax used to access the timer.

 

1) Clearing the timer status register 

 

Various flags are supposed to be cleared by simply doing a read of the status register.

 

The sample code I am using uses this statement to clear the status register!

 

TC0->TC_CHANNEL->TC_SR;

 

I am assuming that a read operation involves moving the contents of the status register somewhere. As far as I can tell in this statement no data is moved out of the status register.

I am surprised that the compiler does not flag an error. 

 

2) Using -> versus . notation

This statement is used to disable interrupts

 

    TC0->TC_CHANNEL->TC_IDR = 0xFFFFFFFF;

 

I see no channel # specified does this mean that this applies to the whole timer?

 

 

This line is used to set the compare value to determine the blink frequency

 

 TC0->TC_CHANNEL[0].TC_RC = 59;

 

But if I try to write this using the same syntax as the interrupt disable ie

 

TC0->TC_CHANNEL[0]->TC_RC =59;

 

I get a compile error : invalid use of -> operator (have 'Tc_Channel')

 

I am not sure if this is a syntax problem or I have a basic misunderstanding about timer channels.

 

I am assuming that each channel of a timer is completely independent of the other channels

ie Timer 0  channels 0 , 1, and 2 can be treated as 3 separate timers

 

Any help would be greatly appreciated :)

 

 

 

It is better to light a candle than curse the darkness.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Have not used this functionality in Arduino. However, I would expect the read syntax to be

 

MyVar = TC0->TC_CHANNEL->TC_SR;

 

This is a COPY operation, not a MOVE operation, in that (normally) the source of the data is not altered. Normally, things like interrupt flag bits are cleared by writing a 1 to that bit. Reading should not alter the contents of the register (though there MAY be a VERY few examples to the contrary, by design).

 

Very possibly, however, TC0->TC_CHANNEL->TC_SR; is a surrogate for a behind-the-scenes clear operation? It should provide an error message if it is not a valid operation.

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

Last Edited: Mon. Apr 18, 2016 - 08:22 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TC0->TC_CHANNEL->TC_SR;

Isn't this just standard C?  TC0 is a struct pointer to a struct.  That struct contains a member TC_CHANNEL, which is a pointer to another struct.  That struct in turn has a member TC_SR, which is a pointer to the status register.

 

This constitutes a read, even without a LHS and an '='.  As the status register is almost certainly declared volatile, the compiler is obliged to perform the read.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Tue. Apr 19, 2016 - 07:36 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thats a new one to me!

 

Is that generally true for C? That is (though no idea why one would want to do it), would:

 

DDRC;

 

generate a read of the DDRC register?

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes.  In general,:

foo;

... generates a read of  the variable foo.

 

Since DDRC is volatile, the compiler is obliged to carry out the read even though it will do nothing with the results.

 

It may seem more natural, or 'proper', to have something like:

sometype_t dummy = TC0->TC_CHANNEL->TC_SR;

... but unless you then make use of dummy later in your code, you may (depending upon the build options) have to contend with a warning/error regarding an ununsed variable.  Some toolchains allow you to handle this via an extension:

sometype_t dummy = TC0->TC_CHANNEL->TC_SR __attribute__ ((__unused__));

... but that's not especially portable.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
(though no idea why one would want to do it)

Consider an AVR UART interrupt handler. If done properly (few seem to) you should check UCSRA for Framing Error, Parity Error or Data Overrun Error. If any are set the value in UDR is invalid but to clear the interrupt you still need to read it so you might do something like:

ISR(UART_RXC_vect) {
    if (UCSRA & (PE_mask | FE_mask | DOR_mask)) {
        report_error_somehow();
        UDR; // force dummy read to clear interrupt condition and error
    }
    else {
        add_to_buffer(UDR);
    }
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hess59 wrote:
I am currently trying to learn how to program the Arduino Due timer in Atmel Studio 7 using a Jtag connector from an ICE.

So you're actually using it purely as a bare SAM3X8E (ARM Cortex-M3) - and this is nothing to do with Arduino at all?

 

So wouldn't this be better in the Cortex-M forum?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Don't see that it really matters - turned out it was a generic C programming question so the mention of SAM3/Due/whatever is pretty incidental.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks joeymorin. As you can see I am still pretty new to C. Writing just a variable name would not fly in 

many other languages.

 

However I am still not clear on question two. I looked up the . and -> operators and they are supposed to be equivalent. So I am

not sure why one works in one situation and the other must be used for another situation.

It is better to light a candle than curse the darkness.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hess59 wrote:
I looked up the . and -> operators and they are supposed to be equivalent.

If you have come away from something you looked up with that impression either (a) you misunderstood or (b) what you were reading was in error.

 

Structure member access using '.' and structure pointer dereference are nothing like one another. You use '.' like so:

void fn(void) {
    struct {
        int n;
        char c;
    } foo;
    foo.n = 12345;
    foo.c = 'A';
}

You cannot use:

void fn(void) {
    struct {
        int n;
        char c;
    } foo;
    foo->n = 12345;
    foo->c = 'A';
}

as if were the same - it is not. But the place you probably most often use -> is when you pass the ADDRESS OF a struct into a function. So you might do this:

typedef struct {
   int n;
   char c;
} foo_t;

void update(foo_t * pFoo);

void fn(void) {
    foo_t foo;

    update(&foo);     
}

void update(foo_t * pFoo) {
    pFoo->n = 23232;
    pFoo->c = 'X';
}

In this the actual instance of the foo_t structure (foo) is created in fn(). It then calls update() and passes it the ADDRESS OF that newly created structure. In update() it can't just do:

void update(foo_t * pFoo) {
    pFoo.n = 23232;
    pFoo.c = 'X';
}

because that would be assuming "pFoo" was actually a structure. But it isn't it is the address of a structure. So you need a way to say "the .n element that is in the structure who's base address is in pFoo" and that is exactly what -> achieves.

 

So in your question (2):

TC0->TC_CHANNEL->TC_IDR = 0xFFFFFFFF;

"TC0" is not a structure. It is the address of a structure. Then (perhaps confusingly) in that structure itself there is a field that also holds the address of another type of structure in an element called TC_CHANNEL. So this is writing 0xFFFFFFFF to a TC_IDR field that is in a structure that is pointed to by TC_CHANNEL and that TC_CHANNEL is itself an element of a structure that is pointed to by "TC0".

 

Don't worry if you don't get this at first - it's fairly complex syntax and it can take a while of doing C to "get it". Maybe start with my most simple example here and work up from there. Consider what might happen if I had done this:

typedef struct {
    long l;
    float f;
} bar_t;

bar_t bar;

typedef struct {
   int n;
   char c;
   bar_t * pBar;   
} foo_t;

foo_t foo = {
    12345,
    'A',
    &bar
};

how would update() change the value of 'f' in the bar structure?

 

(I almost managed to confuse myself making up that contrived example!!)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I looked up the . and -> operators and they are supposed to be equivalent.

They most certainly are not equivalent.  Where did you 'look that up'?

 

The . operator is used to access a member of a struct or union:

struct foo {
    int x;
    int y;
};

Now foo.x will refer to the member named x in foo.

 

What if foo is a pointer to a structure?:

typedef struct {
    int x;
    int y;
} foo_t;

foo_t *foo;

How do I get at the member x?

(*foo).X

C provides a kind of syntactic sugar to make that a bit less awkward:

foo->X

Now if you have a number of nested structs:

typedef struct {
    int fred;
    int frog;
} thing1_t;

typedef struct {
    double garply;
    double waldo;
} thing2_t;

typedef struct {
    thing1_t *x;
    thing2_t *y;
} stuff_t;

stuff_t *foo;

Now I have a pointer to a struct, named foo.  That struct consists of a couple of pointers, each pointing to a different struct themselves.  Those structs in turn contain members of basic type.

 

To get at the double garply, I can:

 *(*foo).y).garply
(*(*foo).y).garply

A bit hard to descipher.

 

Alternately:

foo->y->garply;

Much more intuitive.

 

Check out section "6.2.1. Pointers and structures" here:

http://publications.gbdirect.co.uk/c_book/chapter6/structures.html

... or any good book on C (like K&R).

 

EDIT: quick-draw clawson beat me to the punch ;-)

EDIT: typo in code (missing left parenthesis).

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Fri. Apr 22, 2016 - 01:55 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A first thought was that "TC0->TC_CHANNEL->TC_SR;" is not in C language because the OP said that it was in "sample code", which means that it could be just a cut-and-paste fragment of code found in an obscure PDF referenced by a deep Google search by a sophomore CS student who partied until the assignment was overdue and is now just "grasping at straws" (English idiom meaning "to try anything and see what happens") .   

 

Does "->" mean anything in any other language?   Remember "My Sharona" by the Knack? An excited pop song recording from the late 1970s?  Everyone thought Sharona was a girl's name and the song was about some duufus howling out his girlfriend's name over and over?  And no one noticed that "Mai Shiro Onna" was Japanese for "(give me) Every White Woman!" even though the song went to #1 in Japan?  So, yeah, getting the language right matters.

 

You might see a construction like  Moe->Larry->Curly if Moe was a node (or leaf) on a binary tree that was being removed from the tree.  But it would be written something like Moe->next = Moe->next->next.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Nice try Simonetta, but it's ASF.  Definitely 'C'.

 

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks joeymorin and clawson for your quick and very detailed responses.

Unfortunately it is taking a while for my C beginner brain to absorb it all.

 

I am consulting the C reference quoted and working through it all by typing in some code.

 

I will post again soon (hopefully today) with my understanding of it 

It is better to light a candle than curse the darkness.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello Joey Morin

 

I consulted the reference you mentioned and it was quite useful.

However I had one difficulty with your example code.

Everything worked except for using

 

*(*foo).y).garply

to access the the double garply;

 

I get an error about expecting a statement before the ')' token

 

When I click the error message the cursor moves just after the y

 

So I looked at the reference and tried some trial and error to come up with this kludge

that seems to work. (Can assign value to the float and no compile error)

 

(*((*foo).y)).garply

Here is my understanding of it working from the inner brackets outward

 

1) (*foo)                                    dereference foo so it is now a structure

 

2) (*foo).y                                 access the y member of the structure which is a pointer to a structure (so now the expression is a pointer)

 

3)*((*foo).y)                             dereference the pointer from step 2 so now we have a structure

 

4) (*((*foo).y)).garply               We need to wrap all of expression in 3 in brackets to insure it is evaluated as a structure before we try to access the structure member garply

 

Does this make sense? If so I fully appreciate using the -> operator instead

 

I have attached the working program for anybody who wants to play with it.

 

What is interesting is that intellisense seems to find something wrong with the expression in 4 but it compiles and runs correctly.

 

I found this to be a source of confusion when working with timer structure expressions on the SAM3X8E (Arduino Due)

 

Sometimes correct expressions were flagged by the intellisense and sometimes incorrect ones were not (followed by a compile error)

 

This has only been my experience when working with timer structures.

 

I tested the code by single stepping through it with the atmel ICE connected to an Arduino Due

 

Attachment(s): 

It is better to light a candle than curse the darkness.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello Clawson

 

I like your question because I had to come up with an expression that mixes . and -> operators

 

here is my code

 

bar.f=1000; // put 1000 directly in f
temp =foo.pBar->f; // access f through a structure that points to it 

foo is a structure so I can follow it with a . 

foo.pBar is a pointer to a structure so I have to dereference it following it with -> structure dereference

 

Thanks again for your help.

 

Now that I have a reasonable understanding of the syntax I can tackle the timer structures.

 

It is better to light a candle than curse the darkness.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Everything worked except for using

*(*foo).y).garply

to access the the double garply;

 

I get an error about expecting a statement before the ')' token

 

When I click the error message the cursor moves just after the y

Good catch!

 

It was just a typo, I missed one of the parenthesis (I should have noticed since they were unbalanced).  I'll edit my post to show the error for posterity.

 

However, the fix is just to add the single missing left parenthesis.

(*(*foo).y).garply;

No need for the extra parentheses you have here:

(*((*foo).y)).garply

The extra parentheses >>do<< help to make it a bit clearer what is a member, and what is being dereferenced.  Remember though that without the parenthesis, '.' has a higher precedence than '*', so that middle pair is unnecessary.

 

Here is my understanding of it working from the inner brackets outward

 

1) (*foo)                                    dereference foo so it is now a structure

correct

 

2) (*foo).y                                 access the y member of the structure which is a pointer to a structure (so now the expression is a pointer)

correct

 

3)*((*foo).y)                             dereference the pointer from step 2 so now we have a structure

works, but outer parenthesis aren't required because '.' has already has higher precedence than '*'

 

EDIT: formatting

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Fri. Apr 22, 2016 - 12:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hess59 wrote:
I like your question because I had to come up with an expression that mixes . and -> operators

There WAS method in my madness after all. cheeky

 

Yup, what I envisaged was something like:

void update(foo_t * pFoo) {
    pFoo->n = 23232;
    pFoo->c = 'X';
    pFoo->bar->f = 3.141592;
}

Which kind of replicates the THING->THING->THING syntax that started all this in #1 ;-)

 

If you were accessing "foo" directly, rather than through a struct pointer that is passed into update() here, then it would have been the (simpler?):

foo.bar->f = 3.141592;

which is very like your read access example:

temp =foo.pBar->f; // access f through a structure that points to it 

but doing a write rather than a read.

 

(it's not shown but clearly your "temp" is going to be a float variable)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello joeymorin

 

I like the 4 bracket solution a lot better!

I think I tried it out near the beginning but I probably got an error because I didn't create an instance of one of the arguments.

 

So now my understanding is:

 

1) (*foo) dereferences a pointer to a structure so now we have a structure

 

2) (*foo).y gives us a member of the structure which is a pointer to another structure

 

3) (*(*foo).y) dereferences the pointer in 2 and turns this into the structure that contains garply

 

4) (*(*foo).y).garply accesses the a member of the structure in 3

 

Thanks again!

It is better to light a candle than curse the darkness.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello Clawson

 

I was able to get it working through the use of the update function. Which definitely kicks it up a notch for me.

 

However I had to make one change.

 

I changed 

 

   pFoo->bar->f = 3.141592;

to 

 

   pFoo->pbar->f = 3.141592;

I have uploaded the file in case anybody wants to play with it.

 

Thanks again

 

I feel I have learned a lot!

 

 

Attachment(s): 

It is better to light a candle than curse the darkness.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hess59 wrote:
However I had to make one change.

Ah that was just me being careless! the fact is that the very reason I often prefix a variable with "p" is to remind myself that it is a "pointer to thing" rather than just a "thing" so it was pretty obvious it should be pbar rather than just bar - silly me!

 

As for syntax like:

(*(*foo).y).garply 

in Joey's examples. I think the whole point he is making to you is that the very reason to use -> rather than (*whatever).  is for the very reason to avoid ending up in parenthesis hell that the (*whatever) syntax will create.

 

So while it's an eyeopener to understand what's going on, in reality you, Joey and I will all choose to use "->" in reality. (which is what the authors of C had in mind for it).