User Tools

Site Tools


arm:atsamc21

Introduction

<WRAP group> <WRAP half column> The SAM C21 family is based on the ARM Cortex-M0+. The specific architecture is ARMv6-M.

The SAM C21 microcontrollers use little endian.

There are two buses present; AHB, Advanced High-performance Bus and APB, Advanced Peripheral Bus. Some peripherals are connected to both of the buses, most are only connected to the APB.

There is also something called IOBUS, that seem to be tightly coupled to the ARM core. It seems that peripherals connected to this can be affected directly with an instruction and change in a single clock-cycle.

</WRAP>

  • 2.8 V – 5 V supply voltage
  • 48 MHz core

<WRAP half column> </WRAP> </WRAP>

Chapters of importance

15 - Gives an understanding of the clock generating and distribution.

SAMC21 Xplained Pro

User guide Product page

Based on ATSAMC21J18A

The SAM21 Xplained Pro development board has some peripherals attached:

  • A LED is connected to PA15.
  • A button is connected to PA28 to GND, no external pull-up
  • A CAN interface is connected to PA24(TX) and PA25(RX)
  • A LIN interface is connected to PA06(TX), PA07(RX) and PB22(EN)
  • A QTouch capacitive touch button to PA05

Some lines are connected to the debugger-MCU that can pass communication to PC. The UART is accessible with any serial monitor. The other debug ports is accesible through a plugin in Atmel studio called Data Visualizer and can be found under the Tools menu.

  • CDC_UART PB10(MCU→PC) and PB11(PC→MCU) (SERCOM0)
  • DGI_I2C PA12(SCL) and PA13(SDA)
  • DGI_SPI PB23(EN), PB01(SCK), PB00(MOSI), PB02(MISO)
  • DGI_GPIO_LEVEL PB12, PB16, PB17, PA28

Using peripherals

Clocks and synchronisation

At startup the clock is configured to 4 MHz.

The initial clock setup is described in chapter 15.7 and chapter 12.

All peripherals interfaces two different clock-domains; their individual General Clock source, and the synchronized APB, or AHB, clock that is interfaced by the CPU. Both of these clock sources need to be configured properly.

A General Clock source is configured by a GCLK_XXXX_CORE register, see chapter 16.8.4 table 16-9 for the register mappings. A peripheral can require several General Clock sources.

The synchronized clock is controlled by a bit mask in the Main Clock system, MCLK chapter 17. To quickly find the relevant registers, refer to the peripherals chapter x.5.3 Product Dependencies - Clocks.

The registers in the peripheral that runs in the General Clock domain is referred to as Core registers.

Each core register has its own synchronization mechanism, which makes it possible to write to different core registers consecutively without problems.

Maximum clock frequencies for different parts of the controller can be found in table 45-8 in chapter 45.6.

MCLK, Main Clock system

Three equivalent examples for enabling the synchronized bus clock for the timer TC0.

MCLK->APBCMASK.bit.TC0_ = 1;
MCLK->APBCMASK.reg |= MCLK_APBCMASK_TC0;
REG_MCLK_APBCMASK |= MCLK_APBCMASK_TC0;

GCLK, Generic Clock system

There are nine Generic Clock Generators. Generator 0 is dedicated to source the Main Clock system and is enabled by default.

Each Generic Clock Generator can be sourced from one of several clock sources. These Generators all have their individual clock divider. Generator 1 is the only generator that can be used as clock source for other generators.

There are several Peripheral Channels. The number is dependent on the number of peripherals in the chip. Maximum 64. There are 41 in the ATSAMC21J18A.

Each Peripheral Channel can be sourced from any one of the Generic Clock Generators. Each Peripheral Channel is harwired to one peripheral. The Peripheral Channel consists of a MUX and a clock gate.

The GENCTRL[x] must be written to as one whole 32-bit register, because of the synchronization mechanism.

Example of how to hook up TC0 to Generator 2

GCLK->GENCTRL[2].reg = GCLK_GENCTRL_DIV(100) | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_OSC48M_Val);
GCLK->PCHCTRL[TC0_GCLK_ID].bit.CHEN = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(GCLK_PCHCTRL_GEN_GCLK2_Val);

Step-by-step

  • (A running clock source.)
  • A Generic Clock Generator must be enabled and configured to use a running clock source.
  • The Generic Clock Generator must be connected to the desired peripheral
  • To interface the peripheral from the CPU, the corresponding synchronized clock must be unmasked in the Main Clock registers.

OSC32KCTRL 32.768 Hz oscillator

Three oscillators: External crystal oscillator XOSC32K, Internal high accuracy oscillator OSC32K and Internal ultra low-power oscillator OSCULP32K

All can run at the same time and be used as sources for different generators.

<wrap hi>There seems to be a problem with the XOSC32K crystal on the Xplained board, it runs ocationally when touching the PCB..</wrap> Hmm.. It seems to be a problem only when step-by-step debugging trhough the synchronizing code while(!OSC32KCTRL→STATUS.bit.XOSC32KRDY);. Now it runs rock solid.

Example code to enable the internal high accuracy oscillator and wait for it to stabilize.

OSC32KCTRL->OSC32K.reg = OSC32KCTRL_OSC32K_ENABLE | OSC32KCTRL_OSC32K_EN32K | OSC32KCTRL_OSC32K_EN1K
			| OSC32KCTRL_OSC32K_STARTUP(7);
while(!OSC32KCTRL->STATUS.bit.OSC32KRDY);

Same goal but different register access:

OSC32KCTRL->OSC32K.bit.STARTUP = 7;
OSC32KCTRL->OSC32K.bit.EN1K = 1;
OSC32KCTRL->OSC32K.bit.EN32K = 1;
OSC32KCTRL->OSC32K.bit.ENABLE = 1;
while(!OSC32KCTRL->STATUS.bit.OSC32KRDY);

<wrap hi>Note that none of the internal oscillators seems to be very accurate without calibration by means of the calibration registers. Not accurate at all. The OSC32K oscillator swung at 45 kHz instead of 32.768 for me.</wrap>

PORT peripheral

ATSAMC21 pinout

Only requires APB clock, CLK_PORT_APB, to be interfaced. This is enabled by default at reset. There is no Generic Clock for the PORT peripheral.

All pins are configured to tri-state mode and the input drivers are disabled, with potential exceptions for JTAG-pins.

Some ways of setting PA15 as output and toggle it:

Using direct register access

REG_PORT_DIRSET0 = PORT_PA15;
 
while (1)
{
	REG_PORT_OUTTGL0 = PORT_PA15;
	for(int i = 400000; i ; --i);
}

Using indirect register access

PORT->Group[0].DIRSET.reg  = PORT_PA15;
 
/* Replace with your application code */
while (1)
{
	PORT->Group[0].OUTTGL.reg = PORT_PA15;
	for(int i = 400000; i ; --i);
}

TC peripheral

The APB clock, CLK_TCx_APB, is required for the peripheral to be interfaced. This is disabled by default at reset. Can be accessed through MCLK.APBCMASK.bit.TCx_.

The Generic Clock, GCLK_TCx, is required for the timer to count.

Since the peripheral has several clock sources, some register accesses require synchronization.

uint16_t last_time, now;
last_time = now = 0;
 
// Set LED pin, PA15, as output
PORT->Group[0].DIRSET.reg  = PORT_PA15;
 
// Setup internal 32k oscillator
OSC32KCTRL->OSC32K.reg = OSC32KCTRL_OSC32K_ENABLE | OSC32KCTRL_OSC32K_EN32K | OSC32KCTRL_OSC32K_EN1K
			| OSC32KCTRL_OSC32K_STARTUP(7);
 
// Enable Generic Clock Generator 3, sourced from the internal 32khz oscillator
GCLK->GENCTRL[3].reg = GCLK_GENCTRL_DIV(0) | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_OSC32K_Val);
 
// Connect the timer 0, TC0, to Generator 3
GCLK->PCHCTRL[TC0_GCLK_ID].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(GCLK_PCHCTRL_GEN_GCLK3_Val);
 
// Enable bus clock for TC0
MCLK->APBCMASK.bit.TC0_ = 1;
 
// Configure timer 0 for 16-bit counter mode
TC0->COUNT16.CTRLA.bit.MODE = TC_CTRLA_MODE(TC_CTRLA_MODE_COUNT16_Val);
 
// Configure prescaler and start timer
TC0->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE | TC_CTRLA_PRESCALER(TC_CTRLA_PRESCALER_DIV1_Val);
 
// Wait for the timer to start
while(TC0->COUNT32.SYNCBUSY.bit.ENABLE);
 
while (1) 
{
	// Request read synchronization of the COUNT register
	TC0->COUNT16.CTRLBSET.reg = TC_CTRLBSET_CMD(TC_CTRLBSET_CMD_READSYNC_Val);
 
	// Wait for the command to be registered
	while(TC0->COUNT16.SYNCBUSY.bit.CTRLB);
 
	// Wait for the COUNT register to be synchronized
	while(TC0->COUNT16.SYNCBUSY.bit.COUNT);
 
	// Read the COUNT register
	now = TC0->COUNT16.COUNT.reg;
 
	if((uint16_t)(now - last_time) > 32768u) // Should be 1 sek
	{
		PORT->Group[0].OUTTGL.reg = PORT_PA15;
		last_time = now;
	}
}

CAN Bus Peripheral

StackOverflow – Undocumented baud calculation

total_tq = sync_seg_tq + (phase_seg1_tq+1) + (phase_seg2_tq+1) where sync_seg_tq == 1 always.

Programming

ASF - Atmel Software Framework

Since the acquisition by Microchip this is referred to as Advanced Software Framework.

OpenOCD

$ openocd -f "interface/cmsis-dap.cfg"  -f "target/at91samdXX.cfg"
$ telnet localhost 4444
> reset halt
> at91samd chip-erase
> flash write_bank 0 main.bin 0
$ arm-none-eabi-gdb main.elf --eval-command="target remote localhost:3333"

A file named openocd.cfg in the same folder as openocd is started in is supposed to be loaded automatically. But sometimes this doesn't seem to work. In this case run openocd -f script_file.fcg

# Filename: openocd.cfg
# or envoke with openocd -f filename.cfg

# Explicit debugger and target config files
#source [find interface/cmsis-dap.cfg]
#source [find target/at91samdXX.cfg]

# Readily available config instead of the explicit setup above
source [find board/atmel_samc21_xplained_pro.cfg]

# Some of the sleep commands seems necessary, otherwise the MCU doesnt seem to react properly

# Set to known state
init
reset init
sleep 25

# Erase flash
at91samd chip-erase
sleep 25

# Write firmware
flash write_bank 0 flash_image.bin 0
sleep 25

# Reset MCU
reset
sleep 25

# Shut down openocd server
shutdown
sleep 25

Getting started

Download and install Atmel Studio

  1. Download Atmel Studio: Atmel Studio 7 Download
  2. Run the installer
    • Uncheck the option to send anonymous information if this is not desired
    • Make sure to check the architecture <wrap hi>SMART ARM MCU</wrap>
    • Select the extension <wrap hi>Atmel Software Framework and Example projects</wrap>
    • Install the drivers when asked to
  3. Open Atmel Studio
  4. Select Tools→Device pack manager. In the window that opens search for ATSAMC21 and install the latest release of ATSAMC21_DFP. Restart atmel studio.
  5. Select Tools→Extensions and Updates. In the window that opens choose Updates in the left panel. Apply all available updates. Restart Atmel Studio and repeat until there are no updates available.
  6. Start a project

Start a new bare metal project

  1. Open Atmel Studio and choose File→New→Project…
  2. In the left panel select Installed→C/C++ and pick GCC C Executable Project. Type a name for the project and press OK.
  3. Find the correct MCU in the list. The Xplained board has the ATSAMC21J18A MCU. Press OK.
  4. The project should now be set up and you can press F5 to start the empty program in debug mode if the Xplained board is connected.

<wrap hi>Note that the Debug config by default has the -O1 optimization flag set.</wrap>

arm/atsamc21.txt · Last modified: 2022/09/12 00:30 by 127.0.0.1

Except where otherwise noted, content on this wiki is licensed under the following license: CC0 1.0 Universal
CC0 1.0 Universal Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki