Simple D20 Pin Toggle Not So Simple

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

Back again.

 

THis time I am just looking to blink an LED.  So I fired up Atmel Start and used all the defaults and named the first 8 pins of PORTB 'MY_PORT_x" where 'x' is the pin number from 0 - 7.

 

In my atmel_start_pins.h file I have this:

#ifndef ATMEL_START_PINS_H_INCLUDED
#define ATMEL_START_PINS_H_INCLUDED

#include <hal_gpio.h>

// SAMD20 has 8 pin functions

#define GPIO_PIN_FUNCTION_A 0
#define GPIO_PIN_FUNCTION_B 1
#define GPIO_PIN_FUNCTION_C 2
#define GPIO_PIN_FUNCTION_D 3
#define GPIO_PIN_FUNCTION_E 4
#define GPIO_PIN_FUNCTION_F 5
#define GPIO_PIN_FUNCTION_G 6
#define GPIO_PIN_FUNCTION_H 7

#define MY_PORT_0 GPIO(GPIO_PORTB, 0)
#define MY_PORT_1 GPIO(GPIO_PORTB, 1)
#define MY_PORT_2 GPIO(GPIO_PORTB, 2)
#define MY_PORT_3 GPIO(GPIO_PORTB, 3)
#define MY_PORT_4 GPIO(GPIO_PORTB, 4)
#define MY_PORT_5 GPIO(GPIO_PORTB, 5)
#define MY_PORT_6 GPIO(GPIO_PORTB, 6)
#define MY_PORT_7 GPIO(GPIO_PORTB, 7)

#endif // ATMEL_START_PINS_H_INCLUDED

Ok, so next I create a little program that based on wading through a lot of files I came up with this:

#include <atmel_start.h>
//#include "sam.h"
#include "hal_delay.h"

int main(void)
{
	/* Initializes MCU, drivers and middleware */
	atmel_start_init();
	
	uint8_t COUNT = 0;
	/* Replace with your application code */
	while (1) {
		COUNT++;
	    
		PORT_IOBUS->Group[1].OUTTGL.reg = MY_PORT_0;		//no good!  flashed portb pin 5 instead!!
		
		delay_ms(250);
	}
}

compiles without a problem.  I go and program the D20 and I am surprised to see PORTB PIN 5 blinking instead!  WTH!

 

Sooo, after some searching here I tried this:

#include <atmel_start.h>
//#include "sam.h"
#include "hal_delay.h"

int main(void)
{
	/* Initializes MCU, drivers and middleware */
	atmel_start_init();
	
	uint8_t COUNT = 0;
	/* Replace with your application code */
	while (1) {
		COUNT++;
	    PORT_IOBUS->Group[1].OUTTGL.reg = PORT_PB00;		//this works  flashed portb pin 0	
	
		
		delay_ms(250);
	}
}

and this does as expected.  Blinks PORTB, pin 0

 

I tried this:

#include <atmel_start.h>
//#include "sam.h"
#include "hal_delay.h"

int main(void)
{
	/* Initializes MCU, drivers and middleware */
	atmel_start_init();
	
	uint8_t COUNT = 0;
	/* Replace with your application code */
	while (1) {
		COUNT++;
	   
		_gpio_toggle_level(GPIO_PORTB, PORT_PB00);		//this works  flashed portb pin 0
		
		
		delay_ms(250);
	}
}

and that worked , PORTB, pin 0 blinks

 

But

#include <atmel_start.h>
//#include "sam.h"
#include "hal_delay.h"

int main(void)
{
	/* Initializes MCU, drivers and middleware */
	atmel_start_init();
	
	uint8_t COUNT = 0;
	/* Replace with your application code */
	while (1) {
		COUNT++;
		_gpio_toggle_level(GPIO_PORTB, MY_PORT_0);		//no good!  flashed portb pin 5 instead!!
				
		
		delay_ms(250);
	}
}

also flashes PORTB, pin 5 as well.

 

It is/was my understanding that when I set up the port in START that the pin names would carry into the project through atmel_start_pins.h, but that does not seem to be the case.

 

Experts, any ideas?

 

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

If you are using AtmelStart.. Trying using the built in GPIO API..

 

gpio_set_pin_level( MY_PORT_0, TRUE );

murph

Debugging - Being a detective in a crime movie where you are also the murderer.

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

murph wrote:

If you are using AtmelStart.. Trying using the built in GPIO API..

 

gpio_set_pin_level( MY_PORT_0, TRUE );

 

THat worked.  It set bit 0, and left the rest logic 0.

 

But if I do this:

gpio_toggle_port_level(GPIO_PORTB, MY_PORT_0);

Port b Pin 5 toggles.

 

If I do this:

gpio_toggle_port_level(GPIO_PORTB, (MY_PORT_0 + 1));

Pins 5 and 0 toggle.

 

Grrrrr...I am missing something simple here and i don't know what it is.

 

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

Step through the code looking at the assembler! The truth should be revealed!

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

Shouldnt your 

gpio_toggle_port_level

be

gpio_toggle_pin_level

 

Just browsing through, if I declare some PINs in Start:

#define PORT_04 GPIO(GPIO_PORTB, 4)
#define PORT_05 GPIO(GPIO_PORTB, 5)

Then the GPIO macro is declared as 

#define GPIO(port, pin) ((((port)&0x7u) << 5) + ((pin)&0x1Fu))

So, the GPIO is a number combining the PORT and the PIN into a single number. 

 

Then, looking over the gpio_ functions:

 

So, gpio_toggle_pin_level unwraps this number into a port and a pin...

:: Morten

 

(yes, I work for Atmel, yes, I do this in my spare time, now stop sending PMs)

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

Thanks Morten!  I see the error of my ways somewhat.  But based on your explanation above, why doesn't the 'gpio_toggle_port_level()' unwrap the number?  from the description in the comments shown both do the same thing, just differently.

 

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

No, port_level takes a port and a mask of pins to toggle, while pin_level takes a GPIO and unwraps it to the port and mask for that pin.

:: Morten

 

(yes, I work for Atmel, yes, I do this in my spare time, now stop sending PMs)