Unable to ioport_set_pin_level for specific pins

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

My foray into ASF isn't going quite as planned wink

 

Following on from this post I'm looking to implement a basic bitbang sequence to a shift register. As I've never used ASF before, I thought I'd get my head around this process by simply toggling a pin from HIGH to LOW every 500ms. Whilst I do have an Xplained board available, I'm using the 'user board' approach in Atmel Studio instead, adding in the required modules using the Wizard. The MCU in question is the ATSAME70Q21. The structure and code I have thus far is as follows:

 

conf_board.h:

 

#ifndef CONF_BOARD_H
#define CONF_BOARD_H

//Bitbang data and clock pins
#define BBDAT                                IOPORT_CREATE_PIN(PIOB, 4)
#define BBCLK                                IOPORT_CREATE_PIN(PIOB, 5)
#define TEST                                 IOPORT_CREATE_PIN(PIOD, 29)

//Clock resonators
#define BOARD_FREQ_SLCK_XTAL                 (32768U)
#define BOARD_FREQ_SLCK_BYPASS               (32768U)
#define BOARD_FREQ_MAINCK_XTAL               (12000000U)
#define BOARD_FREQ_MAINCK_BYPASS             (12000000U)
#define BOARD_MCK                            CHIP_FREQ_CPU_MAX
#define BOARD_OSC_STARTUP_US                 15625

#endif // CONF_BOARD_H

 

init.c:

 

#include <asf.h>
#include <board.h>
#include <conf_board.h>

void board_init(void)
{
	/* This function is meant to contain board-specific initialization code
	 * for, e.g., the I/O pins. The initialization can rely on application-
	 * specific board configuration, found in conf_board.h.
	 */

	WDT->WDT_MR = WDT_MR_WDDIS;
	ioport_init();

	ioport_reset_pin_mode(BBCLK);

	ioport_set_pin_dir(BBCLK, IOPORT_DIR_OUTPUT);
	ioport_set_pin_dir(BBDAT, IOPORT_DIR_OUTPUT);
	ioport_set_pin_dir(TEST, IOPORT_DIR_OUTPUT);
}

 

main.c:

 

#include <asf.h>

int main (void)
{
	/* Insert system clock initialization code here (sysclk_init()). */
        sysclk_init();

	board_init();

	bool pin_level;

	while (1) {

		pin_level = ioport_get_pin_level(BBCLK);

		if (pin_level) {
			ioport_set_pin_level(BBCLK, IOPORT_PIN_LEVEL_LOW);
		} else {
			ioport_set_pin_level(BBCLK, IOPORT_PIN_LEVEL_HIGH);
		}
		delay_ms(500);
	}

	/* Insert application code here, after the board has been initialized. */
}

 

As you can see, I define 3 pins:

  1. BBDAT (PB4 - pin 105)
  2. BBCLK (PB5 - pin 109)
  3. TEST (PD29 - pin 108)

 

In the main loop, the current value of the chosen pin is read (pin_level), and its value is then swapped in the if statement. I understand ioport provides a toggle function, but I'm doing it this way to make it easier to step through. I have a breakpoint on the 500ms delay, and an Action to print the value of pin_level.

 

When I run main.c with TEST as the ioport pin, pin_level switches between true and false as planned, which I've verified on my board with a multimeter. However, when I use either BBDAT or BBCLK, pin_level is always false (also verified with a multimeter).

 

Given that PB4 and PB5 are TWIHS pins, I had thought that maybe some muxing had been setup in the background, but I've reset the pin mode (via the ioport macro), made sure that none of the linked ASF libraries or modules have anything remotely related to TWIHS, so I'm not sure if that's the case. One difference to note from the datasheet is that PB4 and PB5 are of type GPIO_MLB, whereas PD29 is of type GPIO_AD. Having done some investigation I don't believe this should cause an issue, as the primary signal and direction for PD4/PD5 is still GPIO and I/O respectively, so they should be addressable/configurable as such.

 

What am I missing here?

Last Edited: Thu. Nov 7, 2019 - 07:44 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you running this in your own board or just using "user board" while still running in the Xplained? If the latter I would guess the pins are used for something.

/Lars

 

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

Hi Lars,

 

Thanks again for your help. I'm running this on my own board. I had initially tried using the Xplained board setup in Atmel Studio, but found it hard to traverse all the various peripheral libraries trying to understand what muxing had taken place, so I've started with a clean 'user board' setup and have only added the clock, delay and ioport services/modules from the Wizard. As far as I can tell there are no special configurations applied to these two pins, they should operate just like any other GPIO, but for some reason I'm not able to control them like I am the TEST pin.

 

Interestingly if I use ioport_set_pin_mode and set IOPORT_MODE_PULLUP for PB4, the pin is a constant HIGH, whereas the same pin mode setting has no impact on PB5. When I do use the pullup mode on PB4, I'm still unable to set the pin level in the main.c function, the pin level is just a constant HIGH.

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

I think I've found the problem. I've studied my schematics and layout once again, and it would appear that I've got the footprint for the connected IC backwards :/ I wish datasheets had a standard way of representing footprints (i.e. bottom view or top view)!

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

Ouch! In addition, from looking at the datasheet, the PB4 and PB5 pins really are not like normal GPIO, they start off as TDI and TDO (test data in and out) check "Table 8-1. System I/O Configuration Pin List" and "19.4.7 System I/O and CAN1 Configuration Register". 

/Lars

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

Lars you are a gentleman and scholar. I'm not sure how I missed that! I've added the below in my init.c and I'm now able to toggle PD4/PD5 :)

 

MATRIX->CCFG_SYSIO |= CCFG_SYSIO_SYSIO4 | CCFG_SYSIO_SYSIO5;

I've desoldered the incorrect footprint component(s) on the board, and will use some breakout boards I have handy to continue development for the time being. Thanks again!