Write to a Port on an ARM Microcontroller using ASF

Created on: 3 June 2016

Part 9 of the ASF ARM Tutorial

How to write to a port or group of pins on an Atmel ARM Cortex microcontroller using ASF in Atmel Studio.

So far in this tutorial series we have looked at how to enable single microcontroller pins as outputs. ASF has functions that can be used to write to an entire port or to selected pins on a port using a mask to select the pins.

In this part of the ASF ARM tutorial four consecutive pins on a port are configured as outputs and LEDs are connected to them. A count value is written to the LEDs by calling an ASF module function.

The following ASF IOPORT module functions are used to configure and write to the port:

  • ioport_enable_port() – enables the selected port or group of port pins determined by a mask value.
  • ioport_set_port_dir() – sets the direction of the port or group of port pins as either inputs or outputs.
  • ioport_set_port_level() – is used to write a value to a port or group of port pins.

Hardware Configuration

Code is run on an Atmel SAM4N Xplained Pro board and four LEDs with series resistors are connected to PORTA pins on the EXT1 connector as shown in the image below. If you are using a different board, make the necessary changes to your hardware and software if needed.

Hardware for Writing to a Port with ASF on the SAM4N Xplained Pro Board
Hardware for Writing to a Port with ASF on the SAM4N Xplained Pro Board

Pins from the 20-pin EXT1 header are connected to the breadboard using a flat ribbon cable with two female IDC connectors and single core jumper wires.

The following pins are used on the pin header:

  • GND – pin 2 of the header is used for common GND on the breadboard power rail.
  • PA11 – EXT1 header pin 15
  • PA12 – EXT1 header pin 17
  • PA13 – EXT1 header pin 16
  • PA14 – EXT1 header pin 18

Each of the four pins is connected to the anode of its own LED and 470Ω series resistor. The other side of each series resistor connects back to the common GND rail on the breadboard. In other words the LEDs are wired in a current sourcing configuration.

Creating the ASF Port Write Project

Create a new ASF project called out_port in Atmel Studio as explained in the ASF quick start checklist.

Add the IOPORT - General purpose I/O service (service) module and the Delay routines (service) module to the project using the ASF Wizard. The System Clock Control service module does not have to be added as it is a dependency of the IOPORT module and so is added automatically as shown in the image from the ASF Wizard below. Expanding the IOPORT module in ASF Wizard reveals that it is dependent on the System Clock Control module. It therefore does not matter if you add this module or not.

ASF Modules Added to the Out Port Project
ASF Modules Added to the Out Port Project

Writing the Port Write Application Code using ASF

The application is written by modifying the following files in the out_port Atmel Studio project.

User Hardware Configuration

Hardware for the board is defined in conf_board.h as shown below. A mask value for the four LEDs is defined and an offset value to shift the mask to the correct position on the port.


#ifndef CONF_BOARD_H
#define CONF_BOARD_H

// 4 LEDs on pins PA11, PA12, PA13 and PA14
// LEDs starting at pin 11 of PORTA
// 4 bit wide mask for LEDs on PORTA

// 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

Hardware Initialization

Hardware initialization functions are called in board_init() which is found in the init.c file.


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

void board_init(void)
    WDT->WDT_MR = WDT_MR_WDDIS;                 // disable watchdog
    ioport_init();                              // call before using IOPORT service
    // enable PORTA and set direction of port as output
    ioport_enable_port(IOPORT_PIOA, EXT_LED_PORTA_MASK);

ioport_enable_port() is called to enable the selected port. In this case PORTA or PIOA is enabled by passing IOPORT_PIOA as the first parameter to this function. The LED mask for the four LEDs defined in conf_board.h is passed as the second parameter to this function.

ioport_set_port_dir() is called to set the direction of the selected port. The port name is passed as the first parameter and the LED mask value as the second parameter. IOPORT_DIR_OUTPUT, the third parameter passed to this function, sets the masked LED pins as outputs on the selected port.

Port Write Application Code

Finally the main application code can be added to main.c. The application listed below simply writes a count to the four LEDs. Because the LEDs are not connected to the bottom four pins of the port, the count must be shifted up to the LEDs on the port.


#include <asf.h>

int main (void)
    uint32_t count = 0;


    while (1) {
        ioport_set_port_level(IOPORT_PIOA, EXT_LED_PORTA_MASK, (count << EXT_LED_PORTA_OFFSET));

ioport_set_port_level() takes the port name as the first parameter, LED or pin mask as the second parameter and the shifted count value as the third parameter. When this function is called, it displays the bottom four bits of the count on the LEDs.