What does this do.....?

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

In a thread in the XMEGA forum I put up a program that I cobbled together from some code I found on the internet.

 

There is one line in there I do not understand and it is this:

io->OUTTGL = PIN1_bm;

More specifically this part:

io->

I am looking through the App notes and such but I cannot find anything about how the line works.

 

While I am at it,

 

PIN1_bm is called BLINK_OUT.  I thought I could be slick and write this:

io->OUTTGL = BLINK_OUT;

but the compiler barfed at this.

 

I know that OUTTGL is a register that can flip the bits(XOR) of the port called out.  And if I want to flip BLINK_OUT I could simply do this:

BLINK_OUT_toggle_level();

instead, but I am looking to understand all the options available.

 

Sooooo, while I continue my searching I was hoping someone might point me in the direction of where I can find out what io-> does and maybe a few of my other questions.

 

Thanks,

JIm

 

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

That references the member of the io struct named OUTTGL. Look up "struct" in K&R or some other reference and all (with respect to the -> notation) will be revealed.

 

As far as I can figure out  xxxx_bm is the mask form of a pin access. I think that it is, effectively, shorthand for (1<<xxxx). That is, it is not the bit number, it is an 8-bit wide mask.

 

Have no experience with the rest of your question.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Sat. Mar 9, 2019 - 02:21 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey Jim

 

I hadn't thought about the Structure, but OUTTGL is a register from the datasheet...will consult the book none the less.

 

YES, xxx_bm is a mask, that much I know.  What I am trying to figure out is why I couldn't simply write 'BLINK_OUT' in place of the mask.

 

Thanks for the tip :)

 

Jim

Edit: page 131 of K&R for the -> explanation.

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

Last Edited: Sat. Mar 9, 2019 - 04:53 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Might be useful to see the barf.
And the definition of PIN1_bm.

Four legs good, two legs bad, three legs stable.

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

Define "is called".

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

It should not barf if you simply do

 

#define BLINKOUT PIN1_bm

 

likewise, at the cost of a variable occupying memory, you should be able  to do:

 

uint8_t BLINKOUT = PIN1_bm;

That is a bit non-standard, though, because the C programming consensus seems to be that "all-caps" signals a precompiler macro. And, in a simple case like this, there is no good reason to use up precious memory.

 

As far as I know, PIN1_bm is predefined in the device headers. And very likely as any of  (1<<1) or 0x02 or 0b00000010 (have not checked). After all, to the precompiler, they are the same and we never see how it is defined in the code we write.

 

West Coast Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Sat. Mar 9, 2019 - 05:42 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John_A_Brown wrote:
And the definition of PIN1_bm.
clawson wrote:
Define "is called".
From Jim's other thread:

jgmdesign wrote:
side note...in START I called PORTA Pin1 'BLINK_OUT'
So how does one request this equivalence in START?  What code does START generate to comply?

"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

So in the gcc avr headers, there is this:

</p>
<p>typedef struct PORT_struct<br />
{<br />
    register8_t DIR;  /* I/O Port Data Direction */<br />
    register8_t DIRSET;  /* I/O Port Data Direction Set */<br />
    register8_t DIRCLR;  /* I/O Port Data Direction Clear */<br />
    register8_t DIRTGL;  /* I/O Port Data Direction Toggle */<br />
    register8_t OUT;  /* I/O Port Output */<br />
    register8_t OUTSET;  /* I/O Port Output Set */<br />
    register8_t OUTCLR;  /* I/O Port Output Clear */<br />
    register8_t OUTTGL;  /* I/O Port Output Toggle */<br />
    register8_t IN;  /* I/O port Input */<br />
    register8_t INTCTRL;  /* Interrupt Control Register */<br />
    register8_t INTMASK;  /* Port Interrupt Mask */<br />
    register8_t reserved_0x0B;<br />
    register8_t INTFLAGS;  /* Interrupt Flag Register */<br />
    register8_t reserved_0x0D;<br />
    register8_t REMAP;  /* Pin Remap Register */<br />
    register8_t reserved_0x0F;<br />
    register8_t PIN0CTRL;  /* Pin 0 Control Register */<br />
    register8_t PIN1CTRL;  /* Pin 1 Control Register */<br />
    register8_t PIN2CTRL;  /* Pin 2 Control Register */<br />
    register8_t PIN3CTRL;  /* Pin 3 Control Register */<br />
    register8_t PIN4CTRL;  /* Pin 4 Control Register */<br />
    register8_t PIN5CTRL;  /* Pin 5 Control Register */<br />
    register8_t PIN6CTRL;  /* Pin 6 Control Register */<br />
    register8_t PIN7CTRL;  /* Pin 7 Control Register */<br />
} PORT_t;

So I'm guessing that io is the base address for the PORT_t;

 

</p>
<p>#include <avr/io.h></p>
<p> </p>
<p>PORT_t *io = (void*) 0xdead;</p>
<p> </p>
<p>void foo() {</p>
<p>  io->OUTTGL = PIN1_bm;</p>
<p>}

 

gcc -mmcu=atxmega64a3 ... -c foo.c -S -o foo.s gives

</p>
<p>foo:<br />
    lds r30,io<br />
    lds r31,io+1<br />
    ldi r24,lo8(2)<br />
    std Z+7,r24<br />
    ret<br />

 

(Pardon the HTML litter; I don't know how that got in there.)

 

edit: and PIN1_bm is defined as 0x02 in all the headers (on my linux box, in /usr/lib/avr/include/avr).

Last Edited: Sun. Mar 10, 2019 - 07:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The HTML is (I'm guessing) because you tried using [ code ] tags rather than the code editor (tags haven't worked since the change over).

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

That's exactly what I did.  Thanks. -- Matt

 

Oh, and the "-c" flag to gcc does not belong: "-S" says "generate assembly".

Last Edited: Sun. Mar 10, 2019 - 09:18 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:
From Jim's other thread:

jgmdesign wrote: side note...in START I called PORTA Pin1 'BLINK_OUT'

 

Thats not my thread.  I was trying to set something up for the OP and stumbled on something and rather than hijack that thread I started this one.

 

John_A_Brown wrote:
And the definition of PIN1_bm

From iox32e5.h

// Generic Port Pins

#define PIN0_bm 0x01
#define PIN0_bp 0
#define PIN1_bm 0x02
#define PIN1_bp 1
#define PIN2_bm 0x04
#define PIN2_bp 2
#define PIN3_bm 0x08
#define PIN3_bp 3
#define PIN4_bm 0x10
#define PIN4_bp 4
#define PIN5_bm 0x20
#define PIN5_bp 5
#define PIN6_bm 0x40
#define PIN6_bp 6
#define PIN7_bm 0x80
#define PIN7_bp 7

 

From port.h

/**
 * \brief Toggle out level on pins
 *
 * Toggle the pin levels on pins defined by bit mask
 *
 * \param[in] mask  Bit mask where 1 means toggle pin level to the corresponding
 *                  pin
 */
static inline void PORTA_toggle_port_level(const uint8_t mask)
{
	PORTA.OUTTGL = mask;
}

jgmdesign wrote:
I know that OUTTGL is a register that can flip the bits(XOR) of the port called out. And if I want to flip BLINK_OUT I could simply do this:

BLINK_OUT_toggle_level();

instead, but I am looking to understand all the options available.

 

I think I now know why I had the issues I had.(THis is a big guess and maybe Morten can determine if I am right or not)

'BLINK_OUT may not be defined globally when you use ATMEL START for some reason.

 

From looking at the .h files if I type:

void togglea0(PORT_t *io)
{
	io->OUTTGL = PIN0_bm;
}

I go straight to the port.h file, where I have a function:

/**
 * \brief Toggle output level on pin
 *
 * Toggle the pin levels on pins defined by bit mask
 *
 * \param[in] pin       The pin number for device
 */
static inline void PORTA_toggle_pin_level(const uint8_t pin)
{
	PORTA.OUTTGL = 1 << pin;
}

 

If BLINK_OUT is not defined the way PINx_bm is, then the compiler barfs.

 

As I wrote earlier, if I type:

void toggle_blinkout(void)
{
	BLINK_OUT_toggle_level();
}

The code hits 'atmel_start_pins.h' where I have:

/**
 * \brief Toggle output level on BLINK_OUT
 *
 * Toggle the pin level
 */
static inline void BLINK_OUT_toggle_level()
{
	PORTA_toggle_pin_level(1);
}

which then takes me to 'port.h' where I have:

/**
 * \brief Toggle output level on pin
 *
 * Toggle the pin levels on pins defined by bit mask
 *
 * \param[in] pin       The pin number for device
 */
static inline void PORTA_toggle_pin_level(const uint8_t pin)
{
	PORTA.OUTTGL = 1 << pin;
}

so, in the case of me using a name for a pin there is extra code involved to get to the same spot to toggle the bit.  Like I said, Morten would be the one to confirm, or correct me on this.

 

As a final test I added this define to the code:

#define F_CPU 2000000UL
#include <atmel_start.h>
#include <avr/io.h>
#include <util/delay.h>

#define BLINK_OUT 0x02;

and changed the function to:

void toggle_blinkout(PORT_t *io)
{
	//	BLINK_OUT_toggle_level();
	io->OUTTGL = BLINK_OUT;
}

and it compiles and runs on actual hardware.  So I am going on the thought that ATMEL_START does not define PORT/PIN names globally,

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

jgmdesign wrote:

#define BLINK_OUT 0x02;

That's going to work a whole lot better without the semi-colon ;-)

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

clawson wrote:

jgmdesign wrote:

#define BLINK_OUT 0x02;

That's going to work a whole lot better without the semi-colon ;-)

 

Works the same with or without.

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

Works the same with or without.

Only in this very simple case but try to || two portpins and the the compiler have a problem  

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

Ahhhhhh!  Hadn't thought of that.

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

jgmdesign wrote:
Thats not my thread.
Correction:  Jim's post in another thread ;-)

"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. Mar 12, 2019 - 03:43 AM